【状压+状态转移】A Famous Airport Managere

https://www.bnuoj.com/v3/problem_show.php?pid=25653

【题意】

  • 给定一个3*3的九宫格,模拟一个停机坪。第一个格子一定是'*',代表take off area,其他的格子可能是'*','B','G'中的一种,'*'代表空地,'B','G'代表蓝色和绿色的飞机。
  • 每次操作都是一个飞机移动到take off area并起飞,在这个过程中其他飞机不能动。
  • 问有多少种飞机起飞的不同序列,同一种颜色的飞机是一模一样的。

【思路】

  • 这个停机坪最多有3^8=6561中不同的状态,可以考虑用三进制状压。
  • 状态之间可以转移。比如:

                可以由转移来,也就是当前的出队序列就是B+pre的出队序列。

                可以由转移来,也就是当前的出队序列就是G+pre的出队序列。

  • 这个出队序列也可以状压,为了表示方便,我们把当前的出队序列表示为pre的出队序列后面接上B或G,这样就可以用[pre]*3+1或[pre]*3+2表示当前状态。
  • 使用set可以自动去重,去掉重复的状态。

【Accepted】

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<string>
  5 #include<cmath>
  6 #include<algorithm>
  7 #include<set>
  8 #include<queue>
  9 using namespace std;
 10 const int maxn=6561;
 11 const int inf=0x3f3f3f3f;
 12 char s[3][4];
 13 int a[10];
 14 int dig[10];
 15 set<int> dp[maxn];
 16 set<int>:: iterator it;
 17 bool v[4][4];
 18 int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
 19 void init()
 20 {
 21     dig[0]=1;
 22     for(int i=1;i<=9;i++)
 23     {
 24         dig[i]=dig[i-1]*3;
 25     }
 26 }
 27 
 28 void BFS()
 29 {
 30     queue<pair<int,int> >Q;
 31     memset(v,false,sizeof(v));
 32     Q.push(make_pair(0,0));
 33     v[0][0]=true;
 34     while(!Q.empty())
 35     {
 36         int x=Q.front().first;
 37         int y=Q.front().second;
 38         Q.pop();
 39     //    cout<<x<<" "<<y<<endl; 
 40         for(int i=0;i<4;i++)
 41         {
 42             int xx=x+dir[i][0];
 43             int yy=y+dir[i][1];
 44             if(v[xx][yy])
 45             {
 46                 continue;
 47             }
 48             if(xx<0||x>=3||y<0||y>=3)
 49             {
 50                 continue;
 51             }
 52             v[xx][yy]=true;
 53             if(s[xx][yy]=='*')
 54             {
 55                 Q.push(make_pair(xx,yy));
 56             }
 57         }
 58     }
 59 }
 60 
 61 void DP()
 62 {
 63     dp[0].insert(0);
 64     for(int i=1;i<dig[8];i++)
 65     {
 66         int now=i;
 67         for(int j=0;j<9;j++)
 68         {
 69             a[8-j]=now%3;
 70             now/=3;
 71         }
 72         for(int j=0;j<3;j++)
 73         {
 74             for(int k=0;k<3;k++)
 75             {
 76                 if(a[j*3+k]==0)
 77                 {
 78                     s[j][k]='*';
 79                 }
 80                 else if(a[j*3+k]==1)
 81                 {
 82                     s[j][k]='B';
 83                 }
 84                 else
 85                 {
 86                     s[j][k]='G';
 87                 }
 88             }
 89         }
 90         BFS();
 91         for(int j=0;j<3;j++)
 92         {
 93             for(int k=0;k<3;k++)
 94             {
 95                 if(v[j][k]&&s[j][k]=='B')
 96                 {
 97                     int pre=i-1*dig[8-3*j-k];
 98                     for(it=dp[pre].begin();it!=dp[pre].end();it++)
 99                     {
100                         dp[i].insert(*(it)*3+1);
101                     }
102                 }
103                 else if(v[j][k]&&s[j][k]=='G')
104                 {
105                     int pre=i-2*dig[8-3*j-k];
106                     for(it=dp[pre].begin();it!=dp[pre].end();it++)
107                     {
108                         dp[i].insert(*(it)*3+2);
109                     }
110                 }
111             }
112         }
113     }
114 }
115 int main()
116 {
117     init();
118     DP();
119     int cas=0;
120     while(~scanf("%s%s%s",s[0],s[1],s[2]))
121     {
122         for(int i=0;i<3;i++)
123         {
124             for(int k=0;k<3;k++)
125             {
126                 if(s[i][k]=='*')
127                 {
128                     a[3*i+k]=0;
129                 }
130                 else if(s[i][k]=='B')
131                 {
132                     a[3*i+k]=1;
133                 }
134                 else 
135                 {
136                     a[3*i+k]=2;
137                 }
138             }
139         }
140         int now=0;
141         for(int i=0;i<9;i++)
142         {
143             now+=a[i]*dig[8-i];
144         }
145         printf("Case %d: ",++cas);
146         cout<<dp[now].size()<<endl; 
147     }
148     
149     return 0;    
150 }
View Code

 

 

    

 

posted @ 2017-07-15 18:51  shulin15  阅读(260)  评论(0编辑  收藏  举报