您的位置:首页 > 其它

染色大战

2016-03-01 22:03 369 查看

题目大意

一个矩形,每个格点初始时是黑或白。

两方轮流操作,每次将一个白格点染黑,如果因为这次操作每将一个1*1正方形的四个格点都变黑可以获得该正方形的权值,一次操作使得获得权值不为0那么可以继续操作。

求两者采用最优策略下先手得到的分数与后手得到的分数的差。

模拟

列个状压DP然后就是模拟题意,注意使用位运算优化常数。

[code]#include<cstdio>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
struct dong{
    int a,b;
};
int i,j,k,l,t,n,m,tot;
int two[25];
int id[25][25];
dong pic[25];
dong f[2][1<<21];
int w[25];
bool bz[2][1<<21];
void dfs(int x,int y){
    if (y==two[n*m]-1) return;
    if (bz[x][y]) return;
    bz[x][y]=1;
    int i,j=0,k=0,t;
    if (x) k=-1;else j=-1;
    fo(i,0,n*m-1)
        if ((two[i]&y)==0){
            t=0;
            if (i%m>0&&i>m-1&&(two[i-1]&y)!=0&&(two[i-m]&y)!=0&&(two[i-m-1]&y)!=0) t+=w[i-m-1];
            if (i%m<m-1&&i>m-1&&(two[i+1]&y)!=0&&(two[i-m]&y)!=0&&(two[i-m+1]&y)!=0) t+=w[i-m];
            if (i%m<m-1&&i<(n-1)*m&&(two[i+1]&y)!=0&&(two[i+m]&y)!=0&&(two[i+m+1]&y)!=0) t+=w[i];
            if (i%m>0&&i<(n-1)*m&&(two[i-1]&y)!=0&&(two[i+m]&y)!=0&&(two[i+m-1]&y)!=0) t+=w[i-1];
            if (t){
                dfs(x,y+two[i]);
                if (x){
                    if (f[x][y+two[i]].b+t>k) k=f[x][y+two[i]].b+t,j=f[x][y+two[i]].a;
                }
                else{
                    if (f[x][y+two[i]].a+t>j) j=f[x][y+two[i]].a+t,k=f[x][y+two[i]].b;
                }
            }
            else{
                dfs(1-x,y+two[i]);
                if (x){
                    if (f[1-x][y+two[i]].b>k) k=f[1-x][y+two[i]].b,j=f[1-x][y+two[i]].a;
                }
                else{
                    if (f[1-x][y+two[i]].a>j) j=f[1-x][y+two[i]].a,k=f[1-x][y+two[i]].b;
                }
            }
        }
    f[x][y].a=j;
    f[x][y].b=k;
}
int main(){
    //freopen("coloring.in","r",stdin);freopen("coloring.out","w",stdout);
    two[0]=1;
    fo(i,1,21) two[i]=two[i-1]*2;
    scanf("%d%d",&n,&m);
    t=0;
    fo(i,1,n){
        fo(j,1,m){
            id[i][j]=tot++;
            scanf("%d",&k);
            if (k) t=t+two[tot-1];
        }
    }
    fo(i,1,n-1)
        fo(j,1,m-1)
            scanf("%d",&w[id[i][j]]);
    dfs(0,t);
    printf("%d\n",f[0][t].a-f[0][t].b);
    //fclose(stdin);fclose(stdout);
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: