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
",t++,dfs((1<<n)-1));
61     }
62     return 0;
63 }
View Code
原文地址:https://www.cnblogs.com/wally/p/3352143.html