loj 1018(状压dp+记忆化搜索)
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=25844
思路:首先预处理出点在同一直线上的所有的点集状态(dp[i][j]),然后记忆化搜索。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define inf 1<<30 7 #define FILL(a,b) memset(a,b,sizeof(a)) 8 9 struct Point{ 10 int x,y; 11 }point[17]; 12 13 int dp[17][17],f[1<<17]; 14 int n; 15 16 bool Judge(int i,int j,int k) 17 { 18 int a=(point[j].y-point[i].y)*(point[k].x-point[i].x); 19 int b=(point[k].y-point[i].y)*(point[j].x-point[i].x); 20 return a==b; 21 } 22 23 void Get_Dp() 24 { 25 FILL(dp,0); 26 for(int i=0;i<n;i++){ 27 for(int j=i+1;j<n;j++){ 28 for(int k=0;k<n;k++){ 29 if(Judge(i,j,k))dp[i][j]|=(1<<k); 30 } 31 } 32 } 33 } 34 35 int dfs(int state) 36 { 37 if(f[state]!=inf)return f[state]; 38 int cnt=0; 39 for(int i=0;i<n;i++)if(state&(1<<i))cnt++; 40 if(cnt==0)return f[state]=0; 41 if(cnt<=2)return f[state]=1; 42 for(int i=0;i<n;i++)if(state&(1<<i)){ 43 for(int j=i+1;j<n;j++)if(state&(1<<j)){ 44 f[state]=min(f[state],dfs(state^(state&dp[i][j]))+1); 45 } 46 break; 47 } 48 return f[state]; 49 } 50 51 int main() 52 { 53 int _case,t=1; 54 scanf("%d",&_case); 55 while(_case--){ 56 scanf("%d",&n); 57 for(int i=0;i<n;i++)scanf("%d%d",&point[i].x,&point[i].y); 58 Get_Dp(); 59 fill(f,f+(1<<n),inf); 60 printf("Case %d: %d\n",t++,dfs((1<<n)-1)); 61 } 62 return 0; 63 }