题意:
就是手机游戏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;
}