LightOJ 1018 Brush (IV)(记忆化搜索)

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1018

题意:平面上有n个点,一次可以擦掉一条直线上的所有点。问至少擦多少次才能将所有点擦完?

思路:b[i][j]表示经过第i、j个点的直线经过的所有点的集合。然后记忆化搜索即可。。。一开始我用b数组(一开始用的是一维数组)

存储可以一次擦掉的点集,然后BFS,TLE了半天。。。

 

View Code
 1 #include <iostream>

 2 #include <cstdio>

 3 #include <cstring>

 4 #define min(x,y) ((x)<(y)?(x):(y))

 5 using namespace std;

 6 

 7 struct Node

 8 {

 9     int x,y;

10 };

11 

12 const int INF=1000000000;

13 Node a[20];

14 int n,f[(1<<16)+5],b[20][20],p[(1<<16)+5];

15 int C,num=0;

16 

17 void deal()

18 {

19     int i,j;

20     for(i=0;i<(1<<16);i++)

21     {

22         p[i]=0;

23         for(j=0;j<16;j++) if(i&(1<<j)) p[i]++;

24     }

25 }

26 

27 inline int OK(Node a,Node b,Node c)

28 {

29     return (a.x-b.x)*(a.y-c.y)==(a.y-b.y)*(a.x-c.x);

30 }

31 

32 void init()

33 {

34     int i,j,k;

35     memset(b,0,sizeof(b));

36     for(i=0;i<n;i++) for(j=i+1;j<n;j++)

37     {

38         for(k=0;k<n;k++) if(OK(a[i],a[j],a[k]))

39           b[i][j]|=(1<<k);

40     }

41 }

42 

43 int DFS(int st)

44 {

45     if(f[st]!=-1) return f[st];

46     int i,j;

47     if(p[st]==0) return f[st]=0;

48     if(p[st]<=2) return f[st]=1;

49     f[st]=INF;

50     for(i=0;i<n;i++) if(st&(1<<i))

51     {

52         for(j=i+1;j<n;j++) if(st&(1<<j))

53         {

54             f[st]=min(f[st],1+DFS(st-(st&b[i][j])));

55         }

56         break;

57     }

58     return f[st];

59 }

60 

61 int main()

62 {

63     deal();

64     for(scanf("%d",&C);C--;)

65     {

66         scanf("%d",&n);

67         int i;

68         for(i=0;i<n;i++) scanf("%d%d",&a[i].x,&a[i].y);

69         init();

70         memset(f,-1,sizeof(f));

71         printf("Case %d: %d\n",++num,DFS((1<<n)-1));

72     }

73     return 0;

74 }

 

 

 

你可能感兴趣的:(搜索)