首页 > 学院 > 开发设计 > 正文

算法提高 金陵十三钗 状压DP

2019-11-06 06:35:37
字体:
来源:转载
供稿:网友

        思路:深度搜索复杂度N!过不了。考虑动态规划:将已经选择的列记为1,未选择表示0,二进制压缩,例如110,就表示选择了第1列和第2列。

     d(i, t)表示当前已经匹配了i行,选择了t这些列。状态转移:

for(int i = 0; i < n; ++i) {		int x = 1 << i;		if(x & val) d = max(d, like[row][i] + dfs(row+1, val - x, k-1));	}

此时总的状态数就是1<<n,相比N!是极大的优化,减少了很多重复情况的搜索。

用记忆化搜索,代码很好写。

#include <cstdio>#include <cmath>#include <algorithm>#include <cstring>#include <utility>#include <string>#include <iostream>#include <map>#include <set>#include <vector>#include <queue>#include <stack>using namespace std;#PRagma comment(linker, "/STACK:1024000000,1024000000") #define eps 1e-10#define inf 0x3f3f3f3f#define PI pair<int, int> typedef long long LL;const int maxn = 13 + 5;int like[maxn][maxn], dp[maxn][1<<13];int n, ans;int dfs(int row, int val, int k) { //row表示行,k表示当前选择了多少列 	if(dp[row][val] != -1) return dp[row][val];	int &d = dp[row][val];	if(k == 1) { //边界 		for(int i = 0; i < n; ++i) {			int x = 1 << i;			if(x & val) return d = like[row][i];		}	}	for(int i = 0; i < n; ++i) {		int x = 1 << i;		if(x & val) d = max(d, like[row][i] + dfs(row+1, val - x, k-1));	}	return d;}int main() {	while(scanf("%d", &n) == 1) {		for(int i = 0; i < n; ++i) 			for(int j = 0; j < n; ++j) {				scanf("%d", &like[i][j]);			}		memset(dp, -1, sizeof(dp));		int start = (1<<n)-1;		printf("%d/n", dfs(0, start, n));	}	return 0;}如有不当之处欢迎指出!


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表