现场时看到这题时感觉和前两天做的一个题目类似(POJ 3732),很早就开敲这题,结果超时了,之后看很少有人过又各种卡题就没去看这题了,今天做了下,稍微加点优化就过了,可惜了...
状态不容易记录,很明显的IDA*题目,第一次做时每次都从(0,0)扫一遍染色,效率太低了,超时,改下做法:
每个块被染色之后他就肯定和(0,0)点相同了,之后无论怎么染色不影响,那么图可以记录为3种状态,被染色过的点(1),下一次可以被染色的点(2) ,其他点(0),搜下去就好了,A*函数为未被染色的颜色的种类
1 #include<cstdio>
2 #include<cstring>
3 using namespace std;
4
5 int maze[10][10],n;
6 int vis[10][10];
7 int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
8 void fill(int x,int y,int c){
9 vis[x][y]=1;
10 for(int i=0;i<4;i++){
11 int tx=x+dir[i][0];
12 int ty=y+dir[i][1];
13 if(tx<0||ty<0||tx>=n||ty>=n) continue;
14 if(vis[tx][ty]==1) continue;
15 vis[tx][ty]=2;
16 if(maze[tx][ty]==c) fill(tx,ty,c);
17 }
18 }
19
20 int exp(int col){
21 int cnt=0;
22 for(int i=0;i<n;i++){
23 for(int j=0;j<n;j++){
24 if(maze[i][j]!=col) continue;
25 if(vis[i][j]==2){
26 cnt++;
27 fill(i,j,col);
28 }
29 }
30 }
31 return cnt;
32 }
33
34 int h(){
35 int col=0;
36 for(int i=0;i<n;i++){
37 for(int j=0;j<n;j++){
38 if(vis[i][j]==1) continue;
39 col|=1<<maze[i][j];
40 }
41 }
42 int cnt=0;
43 while(col){
44 col&=(col-1);
45 cnt++;
46 }
47 return cnt;
48 }
49
50 int dep;
51 bool dfs(int d){
52 if(d==dep) return h()==0;
53 if(h()+d>dep) return false;
54
55 for(int i=0;i<=5;i++){
56 int tvis[10][10];
57 memcpy(tvis,vis,sizeof(vis));
58 if(exp(i)==0) continue;
59 if(dfs(d+1)) return true;
60 memcpy(vis,tvis,sizeof(vis));
61 }
62 return false;
63 }
64
65 int main(){
66 while(scanf("%d",&n),n){
67 for(int i=0;i<n;i++){
68 for(int j=0;j<n;j++){
69 scanf("%d",&maze[i][j]);
70 }
71 }
72 memset(vis,0,sizeof(vis));
73 fill(0,0,maze[0][0]);
74
75 dep=0;
76 while(true){
77 if(dfs(0)) break;
78 dep++;
79 }
80 printf("%d\n",dep);
81 }
82 }
POJ 3732 Paint Me Less
赛前刚做过的题目,这题是4×4的矩阵,但是每个点都可以染色,最后要求颜色为全为0
某个块染色的时候只有染成0或者和周围四个块的某一个相同即可,其他颜色没必要去尝试,然后对每一层的状态加一个hash就能过了,A*为非0的颜色种类个数
1 #include<cstdio>
2 #include<cstring>
3 #include<bitset>
4 using namespace std;
5
6 int maze[5][5];
7 bool ucol[20];
8 int lx,ly;
9
10 int dep;
11 inline int h(){
12 bool col[20];
13 memset(col,false,sizeof(col));
14 for(int i=0;i<lx;i++){
15 for(int j=0;j<ly;j++){
16 col[maze[i][j]]=true;
17 }
18 }
19 int cnt=0;
20 for(int i=1;i<20;i++){
21 cnt+=col[i];
22 }
23 return cnt;
24 }
25
26 int dir[4][2]={{1,0},{0,1},{0,-1},{-1,0}};
27 void fill(int x,int y,int c){
28 int tc=maze[x][y];
29 maze[x][y]=c;
30 for(int i=0;i<4;i++){
31 int tx=x+dir[i][0];
32 int ty=y+dir[i][1];
33 if(tx<0||ty<0||tx>=lx||ty>=ly) continue;
34 if(maze[tx][ty]!=tc) continue;
35 fill(tx,ty,c);
36 }
37 }
38
39 bitset<1000007> vis[17];
40 unsigned zip(){
41 unsigned z=0;
42 for(int i=0;i<lx;i++){
43 for(int j=0;j<ly;j++){
44 z=maze[i][j]+z*131;
45 }
46 }
47 return z%1000007;
48 }
49
50 int ans[20][3];
51 bool dfs(int d){
52 int th=h();
53 if(d==dep) return !th;
54 if(d+th>dep) return false;
55 for(int i=0;i<lx;i++){
56 for(int j=0;j<ly;j++){
57 bool tcol[20];
58 memset(tcol,false,sizeof(tcol));
59 tcol[0]=true;
60 for(int k=0;k<4;k++){
61 int tx=i+dir[k][0];
62 int ty=j+dir[k][1];
63 if(tx<0||ty<0||tx>=lx||ty>=ly) continue;
64 tcol[maze[tx][ty]]=true;
65 }
66 for(int k=0;k<20;k++){
67 if(k==maze[i][j]) continue;
68 if(!tcol[k]) continue;
69 int tmp[5][5];
70 memcpy(tmp,maze,sizeof(tmp));
71 fill(i,j,k);
72 ans[d][0]=i; ans[d][1]=j; ans[d][2]=k;
73 int _z=zip();
74 if(vis[d][_z]){
75 memcpy(maze,tmp,sizeof(tmp));
76 continue;
77 }
78 vis[d][_z]=true;
79 if(dfs(d+1)) return true;
80 memcpy(maze,tmp,sizeof(tmp));
81 }
82 }
83 }
84 return false;
85 }
86
87
88 int main(){
89 while(~scanf("%d%d",&lx,&ly)){
90 memset(ucol,false,sizeof(ucol));
91 ucol[0]=true;
92 for(int i=0;i<lx;i++){
93 for(int j=0;j<ly;j++){
94 scanf("%d",&maze[i][j]);
95 ucol[maze[i][j]]=true;
96 }
97 }
98 dep=0;
99 while(true){
100 for(int i=0;i<dep;i++) vis[i].reset();
101 if(dfs(0)) break;
102 dep++;
103 }
104 printf("%d\n",dep);
105 for(int i=0;i<dep;i++){
106 printf("%d %d %d\n",ans[i][0]+1,ans[i][1]+1,ans[i][2]);
107 }
108 }
109 }