首页 > 代码库 > poj1185炮兵阵地 正确代码及错误代码分析

poj1185炮兵阵地 正确代码及错误代码分析

  Solution:状态压缩

因为设置炮兵的局限性(同行两炮兵相差要大于2),一行10个数最多有60种可能性(程序计算)

  其中判断可能性的好方法是:

         if ((i & (i << 1))==0 && (i & (i << 2))==0
             && (i & (i >> 1))==0 && (i & (i >> 2))==0)

      代表不能有左1,左2,右1,右2相邻的1

行数相差2以上,两行互相之间没有影响

  

  if j,k,l不冲突

f[i][j][k]=max(f[i][j][k],f[i-1][k][l]+v[j])

其中i为第i行,j为第i行的状态,k为第(i-1)行的状态,l为第(i-2)行的状态,v为在第i行的状态j可以设置的炮兵数

f[i][j][k]为前i行,以j,k状态下设置的最多的炮兵数,而第i行设置炮兵只与i-1,i-2行有关(前i行中)

时间复杂度:n*f(t)*f(t)*f(t)

f(t)为一行t个数,设置炮兵的可能性

n<=100,m<=10 即 100*60*60*60=21600000

事实上,由于地形的限制(山地不能建炮兵)和行与行之间的限制(同列两炮兵相差要大于2),时间复杂度小于此

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 
  4 int max(int a,int b)
  5 {
  6     if (a>b)
  7         return a;
  8     else
  9         return b;
 10 }
 11 
 12 int main()
 13 {
 14     //100*1024*1024
 15     int i,j,k,l,m,n,f[100][61][61],use[100][61],map[100]={0},s[100],v[1024]={0},ans=0,g=0;
 16     int er[11]={1,2,4,8,16,32,64,128,256,512,1024};
 17     char c;
 18     scanf("%d%d",&m,&n);
 19     scanf("%c",&c);
 20     for (i=0;i<m;i++)
 21     {
 22         for (j=n-1;j>=0;j--)
 23         {
 24             scanf("%c",&c);
 25             if (c==H)
 26                 map[i]+=er[j];
 27         }
 28         scanf("%c",&c);
 29     }
 30     /*
 31     for (i=0;i<m;i++)
 32         printf("%d\n",map[i]);
 33     printf("\n");
 34     */
 35     for (i=0;i<er[n];i++)
 36         if ((i & (i << 1))==0 && (i & (i << 2))==0
 37             && (i & (i >> 1))==0 && (i & (i >> 2))==0)
 38             {
 39                 ans++;
 40                 s[ans]=i;
 41                 j=i;
 42                 while (j)
 43                 {
 44                     j&=(j-1);
 45                     v[ans]++;
 46                 }
 47             }
 48     /*
 49     printf("ans=%d\n",ans);
 50     for (i=0;i<er[n];i++)
 51         printf("%d %d个 ",s[i],v[i]);
 52     */
 53     //init
 54     for (i=0;i<m;i++)
 55         use[i][0]=0;
 56     for (i=0;i<m;i++)
 57         for (j=1;j<=ans;j++)
 58             for (k=1;k<=ans;k++)
 59                 f[i][j][k]=0;
 60     //row
 61     for (i=0;i<m;i++)
 62         //each row , posibility
 63         for (j=1;j<=ans;j++)
 64             if ((map[i] & s[j])==0)
 65             {
 66                 use[i][0]++;
 67                 use[i][use[i][0]]=j;
 68 
 69                 //编号 cur + bcur + bpre
 70                 if (i>=2)
 71                 {
 72                     for (k=1;k<=use[i-1][0];k++)
 73                         if ((s[j] & s[use[i-1][k]])==0)
 74                             for (l=1;l<=use[i-2][0];l++)
 75                                 if ((s[j] & s[use[i-2][l]])==0
 76                                     && (s[use[i-1][k]] & s[use[i-2][l]])==0)
 77                                         f[i][j][use[i-1][k]]=max(f[i][j][use[i-1][k]],f[i-1][use[i-1][k]][use[i-2][l]]+v[j]);
 78                 }
 79                 else if (i==1)
 80                 {
 81                     for (k=1;k<=use[i-1][0];k++)
 82                         if ((s[j] & s[use[i-1][k]])==0)
 83                             f[i][j][use[i-1][k]]=max(f[i][j][use[i-1][k]],f[i-1][use[i-1][k]][0]+v[j]);
 84                 }
 85                 else
 86                     f[i][j][0]=v[j];
 87 
 88             }
 89     if (m!=1)
 90     {
 91         for (k=1;k<=use[m-1][0];k++)
 92             for (l=1;l<=use[m-2][0];l++)
 93                 if ((s[use[m-1][k]] & s[use[m-2][l]])==0)
 94                     g=max(g,f[m-1][use[m-1][k]][use[m-2][l]]);
 95     }
 96     else
 97     {
 98         for (k=1;k<=use[m-1][0];k++)
 99             g=max(g,f[m-1][use[m-1][k]][0]);
100     }
101     printf("%d\n",g);
102     /*
103     for (i=0;i<m;i++)
104     {
105         for (j=1;j<=ans;j++)
106             for (k=1;k<=ans;k++)
107                 //printf("f[%d][%d][%d]=%d\n",i,j,k,f[i][j][k]);
108                 printf("%d ",f[i][j][k]);
109         printf("\n\n");
110     }
111         for (k=1;k<=use[m-1][0];k++)
112             for (l=1;l<=use[m-2][0];l++)
113                 printf("%d %d %d\n",s[use[m-1][k]],s[use[m-2][l]],f[m-1][use[m-1][k]][use[m-2][l]]);
114     */
115     return 0;
116 }

 

错误代码:

  if j,k,l不冲突

  f[i][j]=max(f[i][j],f[i-2][l]+v[k]+v[j]);

其中i为第i行,j为第i行的状态,k为第(i-1)行的状态,l为第(i-2)行的状态,v为在第i行的状态j可以设置的炮兵数

f[i][j]为前i行,以j状态下设置的最多的炮兵数

  但是l,k可能会发生冲突,在f[i-2][l]下,第(i-1)行不能用k状态

第三行,在第1,4个建炮兵情况下,

8 4

HPPH   

PPPP-----是以右上方的P为基础,与第三行发生冲突

HPPH

PHHP

PHHP

HPPH

PPPP

HPPH

 

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 int max(int a,int b)
 5 {
 6     if (a>b)
 7         return a;
 8     else
 9         return b;
10 }
11 
12 int main()
13 {
14     int i,j,k,l,m,n,f[100][1024],use[100][60],map[100]={0},s[100],v[1024]={0},ans=0,g=0;
15     int er[11]={1,2,4,8,16,32,64,128,256,512,1024};
16     char c;
17     scanf("%d%d",&m,&n);
18     scanf("%c",&c);
19     for (i=0;i<m;i++)
20     {
21         for (j=n-1;j>=0;j--)
22         {
23             scanf("%c",&c);
24             if (c==H)
25                 map[i]+=er[j];
26         }
27         scanf("%c",&c);
28     }
29     /*
30     for (i=0;i<m;i++)
31         printf("%d\n",map[i]);
32     printf("\n");
33     */
34     for (i=0;i<er[n];i++)
35         if ((i & (i << 1))==0 && (i & (i << 2))==0
36             && (i & (i >> 1))==0 && (i & (i >> 2))==0)
37             {
38                 ans++;
39                 s[ans]=i;
40                 j=i;
41                 while (j)
42                 {
43                     j&=(j-1);
44                     v[i]++;
45                 }
46             }
47     /*
48     printf("ans=%d\n",ans);
49     for (i=0;i<er[n];i++)
50         printf("%d ",v[i]);
51     */
52     for (i=0;i<m;i++)
53         use[i][0]=0;
54     for (i=0;i<m;i++)
55         for (j=0;j<er[i];j++)
56             f[i][j]=0;
57     //row
58     for (i=0;i<m;i++)
59     {
60         //each row , posibility
61         for (j=1;j<=ans;j++)
62             if ((map[i] & s[j])==0)
63             {
64                 use[i][0]++;
65                 use[i][use[i][0]]=s[j];
66                 if (i>=2)
67                 {
68                     for (k=1;k<=use[i-1][0];k++)
69                         if ((s[j] & use[i-1][k])==0)
70                             for (l=1;l<=use[i-2][0];l++)
71                                 if ((s[j] & use[i-2][l])==0
72                                     && (use[i-1][k] & use[i-2][l])==0)
73         f[i][s[j]]=max(f[i][s[j]],f[i-2][use[i-2][l]]+v[use[i-1][k]]+v[s[j]]);
74                 }
75                 else if (i==1)
76                 {
77                     for (k=1;k<=use[i-1][0];k++)
78                         if ((s[j] & use[i-1][k])==0)
79         f[i][s[j]]=max(f[i][s[j]],f[i-1][use[i-1][k]]+v[s[j]]);
80                 }
81                 else
82                     f[i][s[j]]=v[s[j]];
83             }
84     }
85     for (i=1;i<=use[m-1][0];i++)
86         g=max(g,f[m-1][use[m-1][i]]);
87     printf("%d\n",g);
88     /*
89     for (i=0;i<m;i++)
90     {
91         for (j=0;j<er[n];j++)
92             printf("%d ",f[i][j]);
93         printf("\n");
94     }
95     */
96     return 0;
97 }

 

poj1185炮兵阵地 正确代码及错误代码分析