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; }