首页 > 代码库 > bzoj3087: Coci2009 misolovke

bzoj3087: Coci2009 misolovke

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

 

bzoj3087: Coci2009 misolovke