1. 程式人生 > >【狀壓+狀態轉移】A Famous Airport Managere

【狀壓+狀態轉移】A Famous Airport Managere

div logs log first 第一個 cout init ring pan

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

    

【狀壓+狀態轉移】A Famous Airport Managere