51nod 1487 占领资源(RMQ+暴力)

来源:互联网 发布:网络购物合同纠纷 编辑:程序博客网 时间:2024/05/16 14:46
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示例
32 2 211110 00 12 2 211110 01 12 2 115610 0
Output示例
4311
孔炤 (题目提供者)
C++的运行时限为:1000 ms ,空间限制为:131072 KB 示例及语言说明请按这里

 允许其他 AC 的用户查看此代码,分享代码才能查看别人的代码并有机会获得勋章


题解:最浅显的做法是枚举两个保护塔,然后求解,复杂度是O(n^2*m^2*k^2)。。。。算了吧

呢还能怎么搞哇。真的是难倒我了,想了半天也没有合适的姿势,只好看了发题解。

然后看了:http://blog.csdn.net/qwb492859377/article/details/51088928大牛的博客,才有了思路。

具体就是枚举一个保护塔的位置,然后处理出来所有和这个保护塔有所冲突的位置以及不冲突的位置。

有所冲突的位置不会超过k^2个,所以暴力就行,不冲突的位置我们可以考虑用RMQ。。。

总复杂度为O(n*m*k^3)....可以过。。。

#include<set>  #include<map>         #include<stack>                #include<queue>  #include<vector>        #include<string>      #include<math.h> #include<time.h>  #include<stdio.h>                #include<iostream>                #include<string.h>                #include<stdlib.h>        #include<algorithm>       #include<functional>        using namespace std;typedef long long ll;#define inf 1000000000           #define mod 1000000007                 #define maxn  20005    #define PI 3.1415926  #define lowbit(x) (x&-x)     #define eps 1e-9char s[105][105];int n, m, k, a[maxn][15], val[maxn], q[maxn];int w[maxn], vis[105][105], b[maxn / 100], c[maxn / 100];int f(int x, int y){return (x - 1)*m + y;}void RMQ(int len){int i, j;for (i = 1;i <= len;i++)a[i][0] = w[i];for (j = 1;(1 << j) <= len;j++)for (i = 1;i + (1 << j) - 1 <= len;i++)a[i][j] = max(a[i][j - 1], a[i + (1 << (j - 1))][j - 1]);}int findmax(int l, int r){int len = 0;while ((1 << (len+1)) <= r - l + 1)len++;return max(a[l][len], a[r - (1 << len) + 1][len]);}int solve(){int ans = 0, i, j, h, t;for(i=1;i<=n;i++)for (j = 1;j <= m;j++){int mx = 0, cnt = 0, id = f(i, j);for (h = 1;h <= k;h++){int dx = i + b[h];int dy = j + c[h];if (dx<1 || dx>n || dy<1 || dy>m)continue;vis[dx][dy] = id;for (t = 1;t <= k;t++){int x = dx - b[t];int y = dy - c[t];if (x<1 || x>n || y<1 || y>m)continue;q[++cnt] = f(x, y);}}q[++cnt] = 0;q[++cnt] = n*m + 1;sort(q + 1, q + cnt + 1);cnt = unique(q + 1, q + cnt + 1) - q - 1;for (h = 1;h < cnt;h++)if (q[h] + 1 <= q[h + 1] - 1)mx = max(mx, findmax(q[h] + 1, q[h + 1] - 1));for (h = 2;h < cnt;h++){int x = (q[h] - 1) / m + 1;int y = (q[h] - 1) % m + 1;int sum = w[f(x, y)];for (t = 1;t <= k;t++){int dx = x + b[t];int dy = y + c[t];if (dx<1 || dx>n || dy<1 || dy>m)continue;if (vis[dx][dy] == id)sum -= s[dx][dy]-'0';}mx = max(mx, sum);}ans = max(ans, mx + w[id]);}return ans;}int main(void){int T, i, j, h;scanf("%d", &T);while (T--){scanf("%d%d%d", &n, &m, &k);for (i = 1;i <= n;i++)for (j = 1;j <= m;j++)vis[i][j] = w[f(i, j)] = 0;for (i = 1;i <= n;i++)scanf("%s", s[i] + 1);for (i = 1;i <= k;i++)scanf("%d%d", &b[i], &c[i]);for(i=1;i<=n;i++)for (j = 1;j <= m;j++){int id = f(i, j);for (h = 1;h <= k;h++){int dx = i + b[h];int dy = j + c[h];if (dx<1 || dx>n || dy<1 || dy>m)continue;w[id] += s[dx][dy] - '0';}}RMQ(n*m);printf("%d\n", solve());}}


原创粉丝点击