light 1011 状态压缩dp

来源:互联网 发布:java中1到100的质数 编辑:程序博客网 时间:2024/06/15 21:52

题意:给一个N*N的二维数组,从中选出N个数 要求不能同行同列, 求这N个数最大数的和    状态压缩。

每个i+1由上一个i推出来,这个直接一个for 搞一下就可以,剩下的就是枚举每个列。开一个dp[1<<16],二进制1表示我不在这一列中选取,0表示在这一列选取了数字。

(1<<n)-1表示初始化 全部都置1,然后从最后一行往前推就可以了。

异或表示去掉一个1,比如1000&1010 = 1000 然后1010^1000 = 0010,这样就去掉了一个1 ,就表示我要选择这列

m-1 就表示换到下一层。


#include <stdio.h>#include <string.h>#include <algorithm>#pragma warning (disable :4996)using namespace std;const int Max = 1 << 16;int dp[Max],a[20][20],n;int dfs(int x, int m){if (m == 0)return 0;if (dp[x])return dp[x];for (int i = 0; i < n; i++){if ((1 << i)&x)//判断第x列有没有被选取过dp[x] = max(dp[x], dfs((1 << i) ^ x, m - 1) + a[m - 1][i]);//如果没被选取,那么要从选这列和不选这列中选值最大的一个,异或符号表示把从里面去掉一个1,就表示选了这列,然后加上对应的权值就可以了}return dp[x];}int main(){int T;scanf("%d", &T);for (int t = 1; t <= T;t++){scanf("%d", &n);for (int i = 0; i < n; i++)for (int j = 0; j < n; j++)scanf("%d", &a[i][j]);memset(dp, 0, sizeof(dp));printf("Case %d: %d\n", t, dfs((1 << n) - 1, n));}return 0;}


0 0
原创粉丝点击