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 }
View Code

请教了下艾神,他说不要去重,太慢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 }

 

posted @ 2016-08-19 22:10  barriery  阅读(689)  评论(0编辑  收藏  举报