uva 11008
状态压缩+记忆化搜索
#include<stdio.h> #include<string.h> #define max 20 #define maxn 2<<18 #define INF 1<<30 int min(int a,int b) { return a>b?b:a; } int g[max][max],f[maxn],limit,x[max],y[max]; int m,n; int dp(int tree) { if(f[tree]!=-1) return f[tree]; int i,j,k,l,t; t=0; for(i=0;i<n;i++) { if((1<<i)&tree) t++; } if(t<=limit) { f[tree]=0; return 0; } if(t==1) { f[tree]=1; return 1; } else { f[tree]=INF; int ans; for(i=0;i<n;i++) { if( (1<<i)&tree ) for(j=0;j<n;j++) { if(i==j) continue; if( (1<< j)&tree && g[i][j] ) ans=dp(tree&(~g[i][j]))+1, f[tree]=min(f[tree],ans); } } return f[tree]; } } int main() { int i,j,k,l,t; scanf("%d",&l); for(t=1;t<=l;t++) { scanf("%d %d",&n,&m); limit=n-m; for(i=0;i<n;i++) { scanf("%d %d",&x[i],&y[i]); } memset(g,0,sizeof(g)); memset(f,-1,sizeof(f)); for(i=0;i<n;i++) //任意两棵树间连线中的树的状态 { for(j=0;j<n;j++) { if(i==j) continue; for(k=0;k<n;k++) { if((y[i]-y[j])*(x[k]-x[j])==(y[k]-y[j])*(x[i]-x[j])) g[i][j]=g[i][j]|(1<<k); } } } printf("Case #%d:\n%d\n",t,dp((1<<n)-1)); if(t!=l) printf("\n"); } return 0; }