题意:
就是手机游戏KAMI...
有一个16*10的矩阵...每个格子里有一个数..范围是1-4...现在将一个格子点成1-4中的一个..那么与其联通的所有格子都会变成这种颜色(所谓联通就是上下左右四个方向能走到的)...现在给出了最优n(n<=8)步会让这个矩阵的所有格子都是相同的颜色...请输出任意一种方案..
题解:
明显的是搜索了...一般的思维是枚举每个联通块..然后枚举染色..这样..就算不考虑染色..枚举联通块的复杂度最高将是P(8,30)..注意是排列不是组合..因为前后顺序是有影响的...那么接下来想到的就是剪枝了..无奈姿势水平不够..怎么剪.第二个样例都跑不出来(等N久不出来)...
大神的方法: 这里
碉堡的是..只要枚举某个联通块后..再这个联通块上枚举找色顺序就可以了...也就是输出答案..在某个点不断的着n次色是一定能出最优方案的...
Program:
#include<iostream> #include<stdio.h> #include<math.h> #include<string.h> #include<queue> #include<map> #include<algorithm> #define MAXN 205 #define ll long long #define oo 1e+10 #define eps 1e-10 using namespace std; struct node { int y,x; }; int w[4][2]={{0,1},{1,0},{0,-1},{-1,0}},ans[MAXN]; bool used[17][11]; char s[17][11]; queue<node> Q; bool dfs(int i,int j,int T) { int x,y,k,e,color; char now[17][11]; node h,p; if (!T) { for (i=1;i<=16;i++) for (j=1;j<=10;j++) if (s[i][j]!=s[1][1]) return false; return true; } color=s[i][j]-'0'; for (k=1;k<=4;k++) if (k!=color) { memcpy(now,s,sizeof(s)); memset(used,false,sizeof(used)); while (!Q.empty()) Q.pop(); h.y=i,h.x=j; used[i][j]=true; Q.push(h); while (Q.size()) { h=Q.front(),Q.pop(); s[h.y][h.x]=k+'0'; for (e=0;e<4;e++) { p.y=h.y+w[e][0],p.x=h.x+w[e][1]; if (s[p.y][p.x]-'0'!=color) continue; if (used[p.y][p.x]) continue; used[p.y][p.x]=true; Q.push(p); } } ans[T]=k; if (dfs(i,j,T-1)) return true; memcpy(s,now,sizeof(s)); } return false; } int main() { int C,cases,T,i,j,x; scanf("%d",&C); for (cases=1;cases<=C;cases++) { scanf("%d",&T); memset(s,0,sizeof(s)); for (i=1;i<=16;i++) scanf("%s",s[i]+1); printf("Case #%d:\n",cases); for (i=1;i<=16;i++) { for (j=1;j<=10;j++) { if (s[i-1][j]==s[i][j] || s[i][j-1]==s[i][j]) continue; if (!dfs(i,j,T)) continue; for (x=T;x>=1;x--) printf("%d %d %d\n",ans[x],i,j); break; } if (j<=10) break; } } return 0; }