题意:
有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 ", dfs(0, sum)); } return 0; }