[51Nod1487]占领资源
2018-01-10 18:55
106 查看
题目大意:
有一个$n\times m(x,m\leq 100)$的网格图,每个格子有一个权值$w_{i,j}(1\leq w_{i,j}\leq 9)$。你可以在图中选两个格子,每个格子$(x,y)$可以接收$k(k\leq 10)$个格子,$(x+dx[1],y+dy[1]),(x+dx[2],y+dy[2]),\ldots,(x+dx[k],y+dy[k])$的权值。超出边界的能量不接收,每个格子的权值最多被接收一次,问最多能接收多少权值。
思路:
考虑选择不同格子,吸收权值的范围不相交的情况,我们可以直接暴力$O(nmk)$求出每个点能吸收的权值,然后选两个最大的加起来即可。
现在每个格子的吸收范围可能会相交,因此我们还需要分两种情况考虑。
我们可以先求出每个点能吸收的权值,然后找出吸收范围会和该点重合的点,不难发现这样的点最多只有$k^2$个。
对于会相交的点,我们暴力求一下可以吸收哪些点的权值,对于不相交的点,可以直接用稀疏表求区间最大值,时间复杂度$O(nmk^2\log(nm))$。
#include<set> #include<cstdio> #include<cctype> #include<algorithm> inline int getint() { register char ch; register bool neg=false; while(!isdigit(ch=getchar())) if(ch=='-') neg=true; register int x=ch^'0'; while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); return neg?-x:x; } inline int getblock() { register char ch; while(!isdigit(ch=getchar())); return ch^'0'; } typedef std::pair<int,int> Point; const int N=100,K=10,logN2=15; std::set<Point> set; bool vis[N*N],b ; int n,m,k,a ,dx[K],dy[K],max[N*N][logN2],q[K*K+3]; inline bool check(const int &x,const int &y) { return x>=0&&x<n&&y>=0&&y<m; } inline int id(const int &x,const int &y) { return x*m+y; } inline int log2(const float &x) { return ((unsigned&)x>>23&255)-127; } inline int query(const int &l,const int &r) { const int k=log2(r-l+1); return std::max(max[l][k],max[r-(1<<k)+1][k]); } inline int calc(const int &x1,const int &y1) { int ret=q[0]=0; for(register int i=0;i<k;i++) { const int x3=x1+dx[i],y3=y1+dy[i]; if(!check(x3,y3)) continue; b[x3][y3]=true; for(register int j=0;j<k;j++) { const int x2=x3-dx[j],y2=y3-dy[j]; if(!check(x2,y2)||vis[id(x2,y2)]) continue; vis[q[++q[0]]=id(x2,y2)]=true; } } for(register int i=1;i<=q[0];i++) { vis[q[i]]=false; } q[++q[0]]=-1; q[++q[0]]=n*m; std::sort(&q[1],&q[q[0]+1]); for(register int i=1;i<q[0];i++) { if(q[i]+1<=q[i+1]-1) { ret=std::max(ret,query(q[i]+1,q[i+1]-1)); } } for(register int i=2;i<q[0];i++) { const int x2=q[i]/m,y2=q[i]%m; int tmp=0; for(register int i=0;i<k;i++) { const int x3=x2+dx[i],y3=y2+dy[i]; if(!check(x3,y3)||b[x3][y3]) continue; tmp+=a[x3][y3]; } ret=std::max(ret,tmp); } for(register int i=0;i<k;i++) { const int x3=x1+dx[i],y3=y1+dy[i]; if(!check(x3,y3)) continue; b[x3][y3]=false; } return ret; } int main() { for(register int T=getint();T;T--) { n=getint(),m=getint(),k=getint(); for(register int i=0;i<n;i++) { for(register int j=0;j<m;j++) { a[i][j]=getblock(); } } for(register int i=0;i<k;i++) { dx[i]=getint(),dy[i]=getint(); if(set.count((Point){dx[i],dy[i]})) { i--,k--; } else { set.insert((Point){dx[i],dy[i]}); } } set.clear(); for(register int x=0;x<n;x++) { for(register int y=0;y<m;y++) { for(register int i=max[id(x,y)][0]=0;i<k;i++) { if(!check(x+dx[i],y+dy[i])) continue; max[id(x,y)][0]+=a[x+dx[i]][y+dy[i]]; } } } for(register int j=1;j<=log2(n*m);j++) { for(register int i=0;j<=log2(n*m-i);i++) { max[i][j]=std::max(max[i][j-1],max[i+(1<<(j-1))][j-1]); } } int ans=0; for(register int x1=0;x1<n;x1++) { for(register int y1=0;y1<m;y1++) { ans=std::max(ans,max[id(x1,y1)][0]+calc(x1,y1)); } } printf("%d\n",ans); } return 0; }
相关文章推荐
- [杂题 暴力 ST表] 51Nod1487 占领资源
- 枚举 51Nod1487 占领资源
- 51nod 1487 占领资源(RMQ+暴力)
- 51nod 1487:占领资源 很好玩很痛苦
- 51Nod-1487-占领资源
- 51node 1487 占领资源【思维+暴力枚举】
- 关于Asp.Net VNext的一些资源
- We7<001>--We7 CMS之报错: HTTP 错误 404.0 - Not Found 您要找的资源已被删除、已更名或暂时不可用。
- android 入门基础 关于工程下的资源类型资料
- 深入 Spring 系列之静态资源处理
- 【案例】国家信息中心:国家公共资源交易服务平台一期工程决策支持服务系统定制项目
- 深度学习&机器学习资源汇总1
- android 给Java Module添加resources资源文件
- Direct3D资源
- [汇编资源]x86-64架构的汇编[网站、电子书、工具]收集
- RAII惯用法:C++资源管理的利器
- 机器学习(Machine Learning)大家与资源
- 网络编程(1)——轻松理解网络资源定位
- 获取资源id,显示图片循环平铺,dither属性解释
- VC2008以资源形式实现多语言版本(非Unicode)