您的位置:首页 > 其它

LightOJ 1011 - Marriage Ceremonies(状态压缩DP)

2016-08-01 12:04 344 查看
题意:输入n 输入n行n列 从n行中找出n个数 保证任意两个都不在同一列 求这些数的和。

思路:dp[i][j]表示前i个选的列状态为j。需要注意的是一个优化,代码中有标识

#include <iostream>
#include <cstdio>
#include <stack>
#include <cstring>

using namespace std;

int a[20][20];
int dp[20][70000];

int main()
{
int t, n;
scanf("%d", &t);
int tt = 1;
while(t--)
{
scanf("%d", &n);
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
scanf("%d", &a[i][j]);
}
}
int maxn = 1<<n;
for(int i=0; i<=n; i++)
for(int j=0; j<=maxn; j++)
dp[i][j] = 0;
for(int i=1; i<=n; i++)
{
for(int j=0; j<maxn; j++)
{
int cnt = 0;
for(int k=0; k<n; k++)//一步优化 就是当前i-1的状态下有不是i-1个组成的话 pass掉
if(j & (1<<k))
cnt++;
if (cnt != i-1)
continue;
for(int k=1; k<=n; k++)
{
int st = 1<<(k-1);
if((st&j)==0)
{
dp[i][st|j] = max(dp[i][st|j], dp[i-1][j]+a[i][k]);
}
}
}
}

printf("Case %d: %d\n", tt++, dp
[(1<<n)-1]);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: