Flood-it!
Flood-it!
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4127/http://acm.split.hdu.edu.cn/showproblem.php?pid=4127
IDA*
这题题意有点不清,我去找了这个游戏玩了会才明白什么回事= =
(游戏链接:http://unixpapa.com/floodit/?sz=26&nc=6)
刚开始我将状态压缩成2^64(用unsigned long long存储,当n=8全部都是一种颜色时用(unsigned long long)(-1)特判),用map去重,dfs判断每次互通的格子,A*是该状态下的颜色种类-1,一次次迭代加深,结果是TLE...
代码如下:
1 #include<cstdio> 2 #include<cmath> 3 #include<iostream> 4 #include<set> 5 #include<map> 6 #include<cstring> 7 #define N 8 8 using namespace std; 9 typedef unsigned long long LL; 10 int mp[N][N],n,deep; 11 bool vis[N][N],ok; 12 map<LL,bool>state; 13 int dx[]={-1,1,0,0}; 14 int dy[]={0,0,-1,1}; 15 LL dfs(int px,int py,int color,LL s){ 16 LL sta=s; 17 vis[px][py]=1; 18 for(int i=0;i<4;++i){ 19 int x=px+dx[i]; 20 int y=py+dy[i]; 21 if(0<=x&&x<n&&0<=y&&y<n) 22 if(color==mp[x][y]||(sta&((LL)1<<(x*n+y)))>0) 23 if(!vis[x][y]){ 24 sta|=((LL)1<<(x*n+y)); 25 sta|=dfs(x,y,color,sta); 26 } 27 } 28 return sta; 29 } 30 LL init(){ 31 ok=0; 32 state.clear(); 33 memset(vis,0,sizeof(vis)); 34 return dfs(0,0,mp[0][0],1); 35 } 36 int Astar(int color,LL s){ 37 set<int>st; 38 st.insert(color); 39 for(int i=0;i<n;++i) 40 for(int j=0;j<n;++j) 41 if((s&(1<<(i*n+j)))==0) 42 if(st.count(mp[i][j])==0) 43 st.insert(mp[i][j]); 44 return (st.size()-1); 45 } 46 void IDAstar(int color,LL sta,int step){ 47 if(ok)return; 48 if(n<8){ 49 if(sta==((LL)1<<n*n)-1){ 50 ok=1; 51 return; 52 } 53 }else{ 54 if(sta==(LL)-1){ 55 ok=1; 56 return; 57 } 58 } 59 int h=Astar(color,sta); 60 if(step+h>deep)return; 61 for(int i=0;i<6;++i){ 62 memset(vis,0,sizeof(vis)); 63 LL s=dfs(0,0,i,sta); 64 if(!state[s]){ 65 state[s]=1; 66 IDAstar(i,s,step+1); 67 state[s]=0; 68 } 69 if(ok)return; 70 } 71 } 72 int main(void){ 73 while(scanf("%d",&n)){ 74 if(n==0)break; 75 for(int i=0;i<n;++i) 76 for(int j=0;j<n;++j) 77 scanf("%d",&mp[i][j]); 78 LL s=init(); 79 if(n<8){ 80 if(s==((LL)1<<(n*n))-1){ 81 printf("0\n"); 82 continue; 83 } 84 }else{ 85 if(s==(LL)-1){ 86 printf("0\n"); 87 continue; 88 } 89 } 90 for(deep=1;!ok;deep++){ 91 state.clear(); 92 state[s]=1; 93 IDAstar(mp[0][0],s,0); 94 } 95 printf("%d\n",deep-1); 96 } 97 }
请教了下艾神,他说不要去重,太慢Orz
好好想了下,好像确实有好多优化点:状态压缩,map去重,A*函数,每次都是dfs= =
之后改进后直接用state[N][N]存储当前状态(1表示与mp[0][0]点相通的格点,2表示与mp[0][0]相通格点邻接的不同格点,0表示剩余格点),用memery[N][N]存储上一个状态;每次染色时判断有没有新增格点(state[i][j]==2&&mp[i][j]==color)有的话才染色;每次dfs的只是这次需要染色的格点域。如此复杂度大大降低了!但是还是TLE了好几发,仔细检查才发现是估价函数A*写搓了QAQ
代码如下:
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<set> 6 #define N 8 7 #define M 6 8 #define met(x) memset(x,0,sizeof(x)) 9 using namespace std; 10 int mp[N][N],n; 11 int state[N][N]; 12 bool mark[M]; 13 int dx[]={0,1,0,-1}; 14 int dy[]={1,0,-1,0}; 15 void dfs(int px,int py,int color){ 16 state[px][py]=1; 17 for(int i=0;i<4;++i){ 18 int x=px+dx[i]; 19 int y=py+dy[i]; 20 if(0<=x&&x<n&&0<=y&&y<n) 21 if(state[x][y]!=1){ 22 if(mp[x][y]==color)dfs(x,y,color); 23 else state[x][y]=2; 24 } 25 } 26 } 27 void init(){ 28 met(state); 29 dfs(0,0,mp[0][0]); 30 } 31 int Astar(int color){ 32 int sum=0; 33 met(mark); 34 /**mark[color]=1; color不应该被mark,估价函数要写的好,搓一点都会TLE**/ 35 for(int i=0;i<n;++i) 36 for(int j=0;j<n;++j) 37 if(state[i][j]!=1&&!mark[mp[i][j]]){ 38 mark[mp[i][j]]=1; 39 sum++; 40 } 41 return sum; 42 } 43 int cnt(int color){ 44 int sum=0; 45 for(int i=0;i<n;++i) 46 for(int j=0;j<n;++j) 47 if(state[i][j]==2&&mp[i][j]==color){ 48 sum++; 49 dfs(i,j,color); 50 } 51 return sum; 52 } 53 bool IDAstar(int deep,int color){ 54 if(deep<Astar(color))return 0; 55 if(deep==0)return 1; 56 for(int i=0;i<M;++i){ 57 int memery[N][N]; 58 memcpy(memery,state,sizeof(state)); 59 if(cnt(i)==0)continue; 60 if(IDAstar(deep-1,i))return 1; 61 memcpy(state,memery,sizeof(memery)); 62 } 63 return 0; 64 } 65 void debug(int i){ 66 printf("\n-----debug %i -----\n",i); 67 } 68 int main(void){ 69 while(scanf("%d",&n)){ 70 if(n==0)break; 71 for(int i=0;i<n;++i) 72 for(int j=0;j<n;++j) 73 scanf("%d",&mp[i][j]); 74 init(); 75 int deep=Astar(mp[0][0]); 76 if(deep==0){ 77 printf("0\n"); 78 }else{ 79 while(!IDAstar(deep,mp[0][0]))deep++; 80 printf("%d\n",deep); 81 } 82 } 83 }