HDU计算机学院大学生程序设计竞赛(2015’12)1007 Pick Game

题意:

有n*m的格子 v[i][j]代表该位置的价值 (n,m<=5)

两个人轮流选格子 只有相邻格子至少有两个为空的才能选

选择之后该格子变空,得到v[i][j]

求问先手能达到的最大价值

 

爆搜可过,状态不多。

记忆化搜索用map记录

4000ms过  无剪枝

还可以加一些剪枝

#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
#include<cmath>
#include<algorithm>
using namespace std;
int fa[15][15],v[15][15],c[15][15];
int n,m;
map<int, int> f;
int dfs(int x, int sum)
{
    int i,j,k;
    int ans = sum;
    if (x == n*m) return 0;
    int pre = 0;
    for (i = 1; i <= n; i++)
        for (j = 1; j <= m; j++) pre += fa[i][j] << ((i - 1)*m + j - 1);
    if (f[pre]) return f[pre];
    for (i = 1; i <= n; i++)
        for (j = 1; j <= m; j++)
            if (c[i][j]<= 2&&fa[i][j]==0)
            {
                fa[i][j] = 1;
                c[i-1][j]--;
                c[i][j-1]--;
                c[i+1][j]--;
                c[i][j+1]--;
                ans=min(ans, dfs(x+1, sum-v[i][j]));
                fa[i][j]=0;
                c[i-1][j]++;
                c[i][j-1]++;
                c[i+1][j]++;
                c[i][j+1]++;
            }
    return f[pre]=sum-ans;
}

int main()
{
    int i,j,k;
    int T;
    scanf("%d", &T);
    while (T--)
    {
        f.clear();
        memset(fa, 0, sizeof(fa));
        scanf("%d%d", &n, &m);
        int sum = 0;
        for (i = 1; i <= n; i++)
            for (j = 1; j <= m; j++)
            {
                scanf("%d", &v[i][j]);
                sum += v[i][j];
                c[i][j] = 4;
                if (i==1||i== n) c[i][j]--;
                if (j==1||j== m) c[i][j]--;
            }

        printf("%d\n", dfs(0, sum));
    }
    return 0;
}

 

  

posted @ 2015-12-26 16:32  Woo95  阅读(202)  评论(0编辑  收藏  举报