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 }
View Code

 

你可能感兴趣的:(dp)