题目链接:http://lightoj.com/volume_showproblem.php?problem=1119
——————————————————————————————————————
题目描述:
好多活,如果一个活在另一个活之前干完,就需要增加费用。
求费用的最小值
——————————————————————————————————————
题目思路:
原来这就是状态压缩dp。。
用位运算+dp做的
——————————————————————————————————————
题目细节:
产生n个1的方法:
m = 1;
m = ((m<<n)-1);
——————————————————————————————————————
源代码:
#include <iostream>
#include<stdio.h>
using namespace std;
#define MAX 17000
#define fmin(a,b) ((a)>(b)? (b):(a))
int m = 0,n = 0;
int p[16][16];
long long int dp[MAX];
int judge(int i,int j)
{
int k = 0,p = 0,t = 0;
for(p = 1;p<=n;p++)
{
t = 1 & j;
if(t)
k++;
j = j>>1;
}
if(k == i) return 1;
else return 0;
}
long long int con(int q,int j)
{
int i = 0,k = 0,t = 1;
int sum = 0;
for(i = 0;i<n;i++)
{
t = 1<<i;
if((t&j) && i!=q)
sum += p[n-q][n-i];
}
for(i = 1;i<n-q;i++)
k = (k<<1)+1;
k = k<<1;
for(i = 0;i<q;i++)
k = (k<<1)+1;
k = k&j;
return dp[k] + sum + p[n-q][n-q];
}
int main()
{
int t = 0;
int i = 0,j = 0,q = 0,k = 0;
scanf("%d",&t);
for(k = 1;k<=t;k++)
{
scanf("%d",&n);
for(i = 1;i<=n;i++)
for(j = 1;j<=n;j++)
scanf("%d",&p[i][j]);
dp[0] = 0;
m = 1;
m = ((m<<n)-1); //队友提供了产生n个1的思路
for(i = 1;i<=n;i++)
for(j = 1;j<=m;j++)
if(judge(i,j))
{
long long int min = (unsigned long long int)(~0)>>1;
if(j == 6)
j = 6;
for(q = 0;q<n;q++)
if((1<<q)&j)
min = fmin(con(q,j),min);
dp[j] = min;
//printf("%d %lld\n",j,dp[j]);
}
printf("Case %d: %lld\n",k,dp[m]);
}
return 0;
}