Description
[misolovke]
给定一个 N*N 的网格.
每个格子里至少会有一个捕鼠器, 并且已知每个格子里的捕鼠器个数.现在需要在 每一行 中选取恰好 K 个连续的格子, 把里面的捕鼠器全部拿走, 并且需要满足
老鼠不能 从网格最左边到网格最右边
也不能 从网格最上面到网格最下面
老鼠行走的方向是 上下左右 4个方向
老鼠只能经过没有捕鼠器的格子
求拿走捕鼠器个数的最大值
Input
第1行: 2 个整数 N, K (2 <= N <= 250, 1 <= K <= N/2)
第2..N+1行: 每行 N 个整数. 表示网格中每个格子里的捕鼠器个数.
Output
第1行: 仅一个整数, 表示拿走捕鼠器个数的最大值
dp,f[i][j][S]表示考虑了前i行,第i行决策为[j-k+1,j],当前决策和左,右,上边界是否联通,捕鼠器的最大个数,转移的时候去掉不合法状态(同时与左右联通或最后一行与上边界联通)
#include<cstdio> int n,k,v[253]; int f[253][253][8]; int _(){ int x=0,c=getchar(); while(c<48)c=getchar(); while(c>47)x=x*10+c-48,c=getchar(); return x; } void maxs(int&a,int b){if(a<b)a=b;} bool chk(int x){return (x&3)!=3;} int main(){ n=_();k=_(); for(int i=1;i<=n;++i){ for(int j=1;j<=n;++j)v[j]=_()+v[j-1]; for(int j=k;j<=n;++j){ int s=v[j]-v[j-k]; for(int d=0;d<8;++d)f[i][j][d]=-0x7fffffff; int w=0; if(j==k)w|=1; if(j==n)w|=2; if(i==1)w|=4; for(int a=k;a<=n;++a){ if(j>a-k&&j<a+k){ for(int d=0;d<8;++d)if(chk(d|w))maxs(f[i][j][d|w],f[i-1][a][d]+s); }else{ if(chk(w))for(int d=0;d<8;++d)maxs(f[i][j][w],f[i-1][a][d]+s); } } } } int ans=-0x7fffffff; for(int i=k;i<=n;++i)for(int d=0;d<4;++d)maxs(ans,f[n][i][d]); printf("%d",ans); return 0; }