LightOJ 1092 Lighted Panels(记忆化搜索)

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

题意:给出一个n*m的格子,每个格子是0或者1。每次翻转格子(i,j)的状态,周围8个格子的状态都要翻转。求最少的翻转次数使得所有格子均为1.

思路:枚举每一行的翻转状态,f[i][j][k]表示第i行,上一行的翻转状态为j,当前行没有翻转时上一行的状态为k的最小值。。。

View Code
 1 #include <iostream>

 2 #include <cstdio>

 3 #include <cstring>

 4 using namespace std;

 5 

 6 const int INF=1000000000;

 7 int C,num=0;

 8 int n,m,f[10][300][300],a[15];

 9 char s[15][15];

10 int cnt[300];

11 

12 void init()

13 {

14     int i,j;

15     for(i=0;i<(1<<8);i++)

16     {

17         cnt[i]=0;

18         for(j=0;j<8;j++) if(i&(1<<j)) cnt[i]++;

19     }

20 }

21 

22 

23 

24 inline int change(int st,int p)

25 {

26     int i,j;

27     for(i=0;i<m;i++) if(p&(1<<i))

28     {

29         for(j=-1;j<=1;j++) if(i+j>=0&&i+j<m)

30         {

31             if(st&(1<<(i+j))) st=st^(1<<(i+j));

32             else st|=(1<<i+j);

33         }

34     }

35     return st;

36 }

37 

38 int DFS(int dep,int pre,int st)

39 {

40     if(dep==n+1)

41     {

42         if(st==(1<<m)-1) return 0;

43         return INF;

44     }

45     int &ans=f[dep][pre][st];

46     if(ans!=-1) return ans;

47     ans=INF;

48     int i,j,st0,temp,p;

49     p=change(a[dep],pre);

50     for(i=0;i<(1<<m);i++) if(change(st,i)==(1<<m)-1)

51     {

52         temp=cnt[i];

53         st0=change(p,i);

54         temp+=DFS(dep+1,i,st0);

55         if(temp<ans) ans=temp;

56     }

57     return ans;

58 }

59 

60 int main()

61 {

62     init();

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

64     {

65         scanf("%d%d",&n,&m);

66         int i,j;

67         for(i=1;i<=n;i++)

68         {

69             scanf("%s",s[i]);

70             a[i]=0;

71             for(j=0;j<m;j++) a[i]=(a[i]<<1)+(s[i][j]=='*');

72         }

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

74         int ans=INF,temp,st;

75         for(i=0;i<(1<<m);i++)

76         {

77             temp=cnt[i];

78             st=change(a[1],i);

79             if(f[1][0][st]!=-1)

80             {

81                 temp+=f[1][0][st];

82             }

83             else

84             {

85                 f[1][0][st]=DFS(2,i,st);

86                 temp+=f[1][0][st];

87             }

88             if(temp<ans) ans=temp;

89         }

90         printf("Case %d: ",++num);

91         if(ans==INF) puts("impossible");

92         else printf("%d\n",ans);

93     }

94     return 0;

95 }

你可能感兴趣的:(Panel)