http://acm.hdu.edu.cn/showproblem.php?pid=4531
这道搜索题挺恶心的。。。比赛时没有写出来。
首先要解决的问题是怎样判断符合条件的状态,即所有一样的颜色是连在一起的。我是采用最简单也最搓的方法,按上下左右顺序给每一个小三角形标号1~36,然后建立一张邻接矩阵图,然后bfs判断。
然后就是主要的暴力枚举部分,每次有12种状态转移的选择,开始时用dfs,但爆栈了。然后改成bfs,又各种TLE。然后就是不断地优化优化。
判重的状态可以用一个整数来表示。
矩阵初始标号为:
1 2 3
4 5 6
7 8 9
那么它的状态就是123456789. 采用哈希判断方法。
代码:
#include<cstdio> #include<cstring> #include<vector> #include<cctype> using namespace std; typedef int int64; const int HashSize = 1000003; // 哈希值尺寸,视情况而定 const int MaxState = 400000; // 共需要存多少个 const int MAXQUE = 500000; int g[40][40]; int mat[3][3]; char str[12][6]; bool vis[40], alpha[150]; bool isCol[3], isRow[3]; int ans; vector<int>G[40]; template<typename Type> class Hash{ public: void init(){ rear=1; memset(head, -1, sizeof(head)); memset(state, -1, sizeof(state)); } int insert(Type s){ int h = hash(s), u = head[h]; while(u!=-1){ if(state[u] == s) return u; //返回所在位置 u = next[u]; } state[rear] = s; next[rear] = head[h]; head[h] = rear++; return rear-1; // 返回新插入的位置 } int find(Type s){ int h = hash(s), u = head[h]; while(u!=-1){ if(state[u] == s) return u; //返回所在位置 u = next[u]; } return 0; } private: int hash(Type x){ int d = ((x&0x7fffffff)%HashSize); return d; } private: int head[HashSize], next[MaxState], rear; Type state[MaxState]; }; Hash<int64>hash; inline void init(); struct Node{ int st; int cnt; }Q[MAXQUE]; int que[100]; char s[40]; inline bool bfs(int st){ int pos=35; while(st>0){ int p = st%10; for(int k=3; k>=0; --k) s[pos--] = str[p][k]; st /= 10; } memset(alpha, 0, sizeof(alpha)); memset(vis, 0, sizeof(vis)); for(int i=0; i<36; ++i)if(!vis[i+1]){ if(alpha[s[i]]) return false; vis[i+1] = true; int front=0, rear=1; que[0] = i+1; while(front < rear){ int u = que[front++]; for(int j=0; j<G[u].size(); ++j){ int v = G[u][j]; if(!vis[v] && s[v-1]==s[u-1]){ vis[v] = true; que[rear++] = v; } } } alpha[s[i]] = true; } return true; } char buf[15]; inline int rotateRow(int st, int row){ sprintf(buf, "%d", st); char tmp = buf[row*3]; buf[row*3] = buf[row*3+1]; buf[row*3+1] = buf[row*3+2]; buf[row*3+2] = tmp; sscanf(buf, "%d", &st); return st; } inline int rotateCol(int st, int col){ sprintf(buf, "%d", st); char tmp = buf[col]; buf[col] = buf[3+col]; buf[3+col] = buf[6+col]; buf[6+col] = tmp; sscanf(buf, "%d", &st); return st; } inline void solve(){ Q[0].st = 123456789; Q[0].cnt = 0; int front=0, rear=1; hash.insert(Q[0].st); while(front < rear){ const Node& q = Q[front++]; if(bfs(q.st)){ ans = q.cnt; return ; } int st; for(int i=0; i<3; ++i){ if(!isRow[i]) { st = rotateRow(q.st, i); if(!hash.find(st)){ hash.insert(st); Q[rear].st = st; Q[rear++].cnt = q.cnt+1; } st = rotateRow(st, i); if(!hash.find(st)){ hash.insert(st); Q[rear].st = st; Q[rear++].cnt = q.cnt+1; } } if(!isCol[i]){ st = rotateCol(q.st, i); if(!hash.find(st)){ hash.insert(st); Q[rear].st = st; Q[rear++].cnt = q.cnt+1; } st = rotateCol(st, i); if(!hash.find(st)){ hash.insert(st); Q[rear].st = st; Q[rear++].cnt = q.cnt+1; } } } } } int main(){ int T, cas=1; init(); scanf("%d", &T); while(T--){ int idx=1; memset(isRow, 0, sizeof(isRow)); memset(isCol, 0, sizeof(isCol)); for(int i=0; i<3; ++i){ for(int j=0; j<3; ++j){ char& ch = str[idx][0]; ch = getchar(); while(!isalpha(ch)) ch=getchar(); for(int k=1; k<5; ++k) str[idx][k] = getchar(); if(str[idx][4] == '1') isRow[i]=isCol[j]=true; mat[i][j] = idx++; } } hash.init(); ans = 100000000; solve(); printf("Case #%d: %d\n",cas++, ans); } return 0; } // ============================= inline void init(){ memset(g, 0, sizeof(g)); g[1][3]=1, g[1][4]=1, g[5][7]=1, g[5][8]=1, g[9][11]=1, g[9][12]=1, g[13][2]=1, g[13][15]=1, g[13][16]=1, g[17][6]=1, g[17][19]=1, g[17][20]=1, g[21][10]=1, g[21][23]=1, g[21][24]=1, g[25][14]=1, g[25][27]=1, g[25][28]=1, g[29][18]=1, g[29][31]=1, g[29][32]=1, g[33][22]=1, g[33][35]=1, g[33][36]=1, g[2][3]=1, g[2][4]=1, g[2][13]=1, g[6][7]=1, g[6][8]=1, g[6][17]=1, g[10][11]=1, g[10][12]=1, g[10][21]=1, g[14][15]=1, g[14][16]=1, g[14][25]=1, g[18][19]=1, g[18][20]=1, g[18][29]=1, g[22][23]=1, g[22][24]=1, g[22][33]=1, g[26][27]=1, g[26][28]=1, g[30][31]=1, g[30][32]=1, g[34][35]=1, g[34][36]=1, g[3][1]=1, g[3][2]=1, g[15][13]=1, g[15][14]=1, g[27][25]=1, g[27][26]=1, g[7][6]=1, g[7][5]=1, g[7][4]=1, g[19][18]=1, g[19][17]=1, g[19][16]=1, g[31][30]=1, g[31][29]=1, g[31][28]=1, g[11][10]=1, g[11][9]=1, g[11][8]=1, g[23][22]=1, g[23][21]=1, g[23][20]=1, g[35][34]=1, g[35][33]=1, g[35][32]=1, g[4][2]=1, g[4][1]=1, g[4][7]=1, g[16][14]=1, g[16][13]=1, g[16][19]=1, g[28][26]=1, g[28][25]=1, g[28][31]=1, g[8][6]=1, g[8][5]=1, g[8][11]=1, g[20][18]=1, g[20][17]=1, g[20][23]=1, g[32][30]=1, g[32][29]=1, g[32][35]=1, g[12][10]=1, g[12][9]=1, g[24][22]=1, g[24][21]=1, g[36][34]=1, g[36][33]=1; for(int i=1; i<=36; ++i){ G[i].clear(); for(int j=1; j<=36; ++j)if(g[i][j]){ G[i].push_back(j); } } }