[GDKOI2016] Day2 染色大战 记忆化搜索

出题人讲这题的时候扯到了模拟退火,遗传算法,alphabeta剪枝等等
然而这题一个记忆化搜索就能跑过去

#include <iostream>
#include <cstdio>
#define INF (1<<30)
#define N 22

using namespace std;
int n,m,tp,e[N][N],map[N][N],v[N][N];
int vis[2][1<<N];
const int fx[] = {0,1,0,-1};
const int fy[] = {1,0,-1,0};

inline void ut(int &x,int y) { x = max(x,y); }
inline void check(int x,int y,int &c) {
    if (map[x][y] && map[x+1][y] && map[x][y+1] && map[x+1][y+1]) c+=v[x][y];
}

int dfs(int x,int mask){
    if (mask == tp) return 0;
    if (vis[x][mask]) return vis[x][mask];
    int ret = -INF;
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++) if (!map[i][j]){
            map[i][j] = 1;
            int val = 0;
            check(i-1,j-1,val); check(i-1,j,val);
            check(i,j-1,val); check(i,j,val);
            if (val) 
                val += dfs(x,mask+e[i][j]);
            else
                val -= dfs(x^1,mask+e[i][j]);
            ut(ret,val);
            map[i][j] = 0;      
        }
    vis[x][mask] = ret;
    return ret;
}
int main() {
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++) 
            e[i][j] = 1<<( (i-1)*m+j-1 );
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++) {
            scanf("%d",&map[i][j]);
            if (!map[i][j]) tp += e[i][j];
        }
    for (int i=1;i<=n-1;i++)
        for (int j=1;j<=m-1;j++) scanf("%d",&v[i][j]);
    //1先手 0后手 
    int ans = dfs(1,0);
    printf("%d\n",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值