您的位置:首页 > 其它

51nod 1487:占领资源 很好玩很痛苦

2016-02-18 13:37 162 查看
1487 占领资源


题目来源: TopCoder

基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题


收藏


关注

有一个矩形区域被划分为N行M列的网格,每个格子里有一定数量的资源并记录在矩阵val中,坐标(x,y)位置上资源量为val[x][y],其val中每个元素的值为0~9的整数。如果你在某个网格(a,b)上造一座保护塔,那么你可以占领K个网格中的资源,这K个格子分别是(a+dx[1],b+dy[1]),(a+dx[2],b+dy[2]),...,(a+dx[K],b+dy[K]),注意(a,b)这格本身可能未必会被占领。现在你能建造不超过2个塔,问最多能占领多少资源?一个网格被多个塔占领时其资源只计算一次。另外如果计算的位置(a+dx[i],b+dy[i])在网格外,则不贡献任何资源。

Input
多组测试数据,第一行一个整数T,表示测试数据数量,1<=T<=5
每组测试数据有相同的结构构成:
每组数据第一行三个整数N,M,K,其中2<=N,M<=100,1<=K<=10。
之后会有N行,每行M个元素,表示val矩阵。每个元素为0~9,占一个字符,元素间没空格。
再接下来有K行,每行两个整数dx[i]与dy[i],其中-(N-1)<=dx[i]<=N-1,-(M-1)<=dy[i]<=(M-1).


Output
每组数据一行输出,即可占领的最大资源总量。


Input示例
3
2 2 2
11
11
0 0
0 1
2 2 2
11
11
0 0
1 1
2 2 1
15
61
0 0


Output示例
4
3
11


这个题自己想了很久。。。困于时间和空间。。。一直想枚举两个点,但这样复杂度就超时了。然后如果对每一个点计算其重叠,这样的话空间又会爆。。。

后来和丁神讨论题解之后,终于在第二天才敲出来。。。

这个题的解题思路真的很服。。。

任何一个点不会与超过k^2个点有公共交点。

因此不妨对每个点单独处理这k^2个特殊位置,而其他位置直接取最大值即可。

代码:

#pragma warning(disable:4996)
#include <iostream>
#include <functional>
#include <algorithm>
#include <cstring>
#include <vector>
#include <string>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <deque>
#include <ctime>;
#include <set>
#include <map>
using namespace std;

typedef long long ll;
#define INF 0x3fffffff
#define rep(i,n) for(int i=0;i<n;i++)  
#define rep1(i,n) for(int i=1;i<=n;i++) 

const ll mod = 1e9 + 7;
const int maxn = 105;

int has[maxn][maxn][105];
int con[maxn][maxn][105];
int sz[maxn][maxn],ha_sz[maxn][maxn];
map<pair<int, int>, int>res;

int n, m, k, ans;
int dx[maxn], dy[maxn], val[maxn][maxn];
int flag_cal[100200];

struct no
{
	int id;
	int val;
}node[100200], node2[100200];

bool cmp(no n1, no n2)
{
	return n1.val > n2.val;
}

void input()
{
	char tmpc;
	int i, j;
	scanf("%d%d%d", &n, &m, &k);
	scanf("%c", &tmpc);

	memset(node, 0, sizeof(node));
	memset(node2, 0, sizeof(node2));
	memset(sz, 0, sizeof(sz));
	memset(ha_sz, 0, sizeof(ha_sz));
	memset(flag_cal, 0, sizeof(flag_cal));

	for (i = 1; i <= n; i++)
	{
		for (j = 1; j <= m; j++)
		{
			scanf("%c", &tmpc);
			val[i][j] = tmpc - '0';
			int d = (i - 1)*m + j;
			node[d].id = d;
		}
		scanf("%c", &tmpc);
	}
	for (i = 1; i <= k; i++)
	{
		scanf("%d%d", &dx[i], &dy[i]);
	}
}

void solve()
{
	int i, j, h, g;
	for (i = 1; i <= n; i++)
	{
		for (j = 1; j <= m; j++)
		{
			for (h = 1; h <= k; h++)
			{
				if (i + dx[h] >= 1 && i + dx[h] <= n&&j + dy[h] >= 1 && j + dy[h] <= m)
				{
					int pos_x = i + dx[h];
					int pos_y = j + dy[h];
					int point_flag = (i - 1)*m + j;
					sz[pos_x][pos_y]++;
					con[pos_x][pos_y][sz[pos_x][pos_y]] = point_flag;
					node[point_flag].val += val[pos_x][pos_y];
					node2[point_flag].val += val[pos_x][pos_y];
				}
			}
		}
	}

	sort(node + 1, node + n*m + 1, cmp);
	ans = 0;
	for (i = 1; i <= n; i++)
	{
		for (j = 1; j <= m; j++)
		{
			res.clear();
			for (h = 1; h <= k; h++)
			{
				if (i + dx[h] >= 1 && i + dx[h] <= n&&j + dy[h] >= 1 && j + dy[h] <= m)
				{
					int pos_x = i + dx[h];
					int pos_y = j + dy[h];
					int s = sz[pos_x][pos_y];
					for (g = 1; g <= s; g++)
					{
						int x = con[pos_x][pos_y][g] / m + 1;
						int y = con[pos_x][pos_y][g] % m;
						if (x == i&&y == j)continue;
						else
						{
							int p1_flag = (i - 1)*m + j;
							int p2_flag = (x - 1)*m + y;
							if (flag_cal[p2_flag])continue;
							int s1 = min(p1_flag, p2_flag);
							int s2 = max(p1_flag, p2_flag);
							res[make_pair(s1, s2)] -= val[pos_x][pos_y];
						}
					}
				}
			}

			for (h = 1; h <= k*k + 1; h++)
			{
				int x = node[h].id / m + 1;
				int y = node[h].id%m;
				int p1_flag = (i - 1)*m + j;
				int p2_flag = (x - 1)*m + y;
				if (flag_cal[p2_flag])continue;
				int s1 = min(p1_flag, p2_flag);
				int s2 = max(p1_flag, p2_flag);
				if (s1 == s2)continue;
				ans = max(ans, res[make_pair(s1, s2)] + node2[p1_flag].val + node[h].val);
				if (res[make_pair(s1, s2)] == 0)
					break;
			}
			flag_cal[(i - 1)*m + j] = 1;
		}
	}
	printf("%d\n", ans);
}

int main()
{
	//freopen("i.txt", "r", stdin);
	//freopen("o.txt", "w", stdout);

	int t;
	scanf("%d", &t);
	while (t--)
	{
		input();
		solve();
	}

	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: