题意:给你一个棋盘,点代表空广场,数字K代表广场上有骑士且骑士每次能跳K步,问是否可以通过移动适当的骑士使得所有的骑士都在一个广场上,如果能,输出最小的移动次数,如果不能,输出-1;
模拟加搜索。可以遍历一下棋盘上每个广场,然后让每个骑士都移动到正在遍历的广场上去,记录下所需的步骤,并更新最小步骤,注意应当用广搜来写,用深搜会超时;
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<map>
#include<vector>
#define INF 0x3f3f3f3f
#define N 12
using namespace std;
int m,n,s,k,Min,ans,flag;
int b[N][N];
char a[N][N];
struct point
{
int x,y,s;
};
point q[110];
int bfs(int startx,int starty,int endx,int endy)//广搜求最短路,数组模拟队列;
{
int next[8][2]= {{1,2},{1,-2},{2,1},{2,-1},{-1,2},{-1,-2},{-2,1},{-2,-1}};
int tx,ty,k,head,tail;
head=tail=1;
q[tail].x=startx;
q[tail].y=starty;
q[tail].s=0;
tail++;
b[startx][starty]=1;
flag=0;
while(head<tail)
{
for(k=0; k<=7; k++)
{
tx=q[head].x+next[k][0];
ty=q[head].y+next[k][1];
if(tx<0||ty<0||tx>m-1||ty>n-1)
continue;
if(b[tx][ty]==0)
{
b[tx][ty]=1;
q[tail].x=tx;
q[tail].y=ty;
q[tail].s=q[head].s+1;
tail++;
}
if(tx==endx&&ty==endy)
{
flag=1;
break;
}
}
if(flag==1)
break;
head++;
}
return q[tail-1].s;
}
int Serach(int endx,int endy)
{
int i,j;
int ans=0;
for(i=0; i<m; i++)
for(j=0; j<n; j++)
{
if(a[i][j]!='.'&&(i!=endx||j!=endy))
{
memset(b,0,sizeof(b));
memset(q,0,sizeof(q));
s=bfs(i,j,endx,endy);//从有骑士的广场上开始广搜,求出该骑士到要求的广场上需要移动多少步骤
if(flag==0)
return -1;
if(s%(a[i][j]-'0')==0)
ans+=s/(a[i][j]-'0');//将骑士移动到要求的广场上需要的总步骤能整除每次移动的步骤的话,总步骤除以每次可以移动多少步,就是移动的次数
else
ans+=s/(a[i][j]-'0')+1;//不能整除的话,需要再加1;
}
}
return ans;
}
int main()
{
int t,i,j;
scanf("%d",&t);
while(t--)
{
int f=0;
scanf("%d%d",&m,&n);
for(i=0; i<m; i++)
for(j=0; j<n; j++)
scanf(" %c",&a[i][j]);
Min=INF;
for(i=0; i<m; i++)
for(j=0; j<n; j++)
{
int mm=Serach(i,j);//搜索每个广场,让骑士移动到这个广场去;
if(mm<Min&&mm>=0)
{
Min=mm;
f=1;
}
}
if(f==0)
printf("Case %d: -1\n",++k);
else
printf("Case %d: %d\n",++k,Min);
}
return 0;
}