hdu 3920 Clear All of Them I
http://acm.hdu.edu.cn/showproblem.php?pid=3920
状态压缩DP.
dp[mask] , 表示mask二进制表示中为1的元素都被击中的最小代价。当然如果有奇数个1就可以忽略了。
dp[mask | tj | tk] = min( dp[mask | tj | tk] , dp[mask]+dis[j,k] ) ; ( tj=(1<<(j-1)) , tk=(1<<(k-1)).
如果n=2,有四个元素的时候
0000=> 0011 0101 1001
0011=> 1111
0101=> 1111
1001=> 1111
状态压缩枚举的时候刚好把所有的组合都考虑在里面了=!
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string.h>
#include <cmath>
#include <vector>
using namespace std;
struct node
{
double x;
double y;
}a[30];
int n, maxint=0;
const int maxn = (1<<20)+10;
const double eps = 1e-8;
const double inf = 2147483647;
double dp[maxn];
double dis[30][30];
double Dist(node p,node q)
{
return sqrt((p.x-q.x)*(p.x-q.x)+(p.y-q.y)*(p.y-q.y));
}
int main()
{
int T,ta=1,i=0,j=0,k=0;
scanf("%d",&T);
while(T--)
{
scanf("%lf %lf",&a[0].x,&a[0].y);
scanf("%d",&n);
for(i=1;i<=2*n;i++)
scanf("%lf %lf",&a[i].x,&a[i].y);
maxint = (1<<(2*n))-1;
for(i=0;i<=2*n;i++)
for(j=i;j<=2*n;j++)
dis[j][i]=dis[i][j]=Dist(a[i],a[j]);
for(i=1;i<=maxint;i++)
dp[i]=inf;
dp[0]=0;
for(i=0;i<=maxint;i++)
{
if(dp[i]==inf)
continue;
int tj=0;
for(j=1;j<=2*n;j++)
{
tj=(1<<(j-1));
if( (tj & i)==0)
break;
}
if(tj==0)
break;
for(k=j+1;k<=2*n;k++)
{
int tk = 1<<(k-1);
if( (tk & i)==0)
{
int tmp=(i|tj|tk);
dp[tmp]=min(dp[tmp],dp[i]+dis[j][0]+dis[j][k]);
dp[tmp]=min(dp[tmp],dp[i]+dis[k][0]+dis[j][k]);
}
}
}
printf("Case #%d: %.2f\n",ta++,dp[maxint]);
}
return 0;
}
浙公网安备 33010602011771号