ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

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;
}

 

posted on 2016-12-17 19:42  nul  阅读(311)  评论(0编辑  收藏  举报