joj 2438
这个呢 是搜索
起初想的是记下到每个点杀k个怪的最短时间
后来发现这样是不够的,因为杀的怪有不同的组合
比如
2 3 5
ooo
ooO
(初始位置为0,0)
到(1,1) 杀3个怪的最短时间是3,但是有两种走法
0,0 0,1 1,1和
0,0 1,0 1,1
但是第一种走法得不到最优解
所以光记下最短时间是不够的
我呢 就是深度优先搜索
关键是减支
1.这个骑士呢,不可能从x,y出发绕了一圈一个小怪也没杀就又回到x,y
2.假设骑士已经升级,如果从当前位置到终点的时间加上当前时间都比已得到的解差的话就没有必要继续搜下去了
#include <iostream>
using namespace std;

char graph[70][70];
int shortest[70][70];

int dir[4][2]=
{
{0,1},
{1,0},
{-1,0},
{0,-1}};
int state[70][70][70];

int n,m,k,ans;

void init()


{
int i,j;
//cin>>n>>m>>k;
for (i=0;i<n;i++)
for (j=0;j<m;j++)
cin>>graph[i][j];
memset(state,-1,sizeof(state));

}

void preDFS(int x,int y)


{
for (int l=0;l<4;l++)

{
int p=x+dir[l][0];
int q=y+dir[l][1];

if (p>=0 && p<n && q>=0 && q<m)
if (graph[p][q]!='#')
if (shortest[p][q]==-1 || shortest[p][q]>shortest[x][y]+1)

{
shortest[p][q]=shortest[x][y]+1;
preDFS(p,q);
}
}
}



void get_shortest()


{
memset(shortest,-1,sizeof(shortest));

shortest[n-1][m-1]=0;

preDFS(n-1,m-1);
}



void DFS(int x,int y,int now,int t)


{
if (shortest[x][y]==-1) return ;
if (ans!=-1)
if (shortest[x][y]+t>=ans) return ;
if (now>=k || (x==n-1 && y==m-1))
if (t+shortest[x][y]<ans || ans==-1)

{
if (x==n-1 && y==m-1 && now<k && graph[n-1][m-1]=='O') return ;
if (shortest[x][y]==-1) return ;
ans=t+shortest[x][y];
return ;
}

for (int l=0;l<4;l++)

{
int p=x+dir[l][0];
int q=y+dir[l][1];

if (p>=0 && p<n && q>=0 && q<m)

{
if (graph[p][q]=='#') continue;

if (graph[p][q]=='O') continue;


if (graph[p][q]=='o')

{
graph[p][q]='.';
state[p][q][now+1]=1;
DFS(p,q,now+1,t+1);
state[p][q][now+1]=-1;
graph[p][q]='o';
continue;
}

if (graph[p][q]=='.' && state[p][q][now]==-1)

{
state[p][q][now]=1;
DFS(p,q,now,t+1);
state[p][q][now]=-1;
continue;
}
}
}
}

int main()


{

int t,now;

while (cin>>n>>m>>k)

{
init();
get_shortest();
if (graph[0][0]=='o')

{
now=1;
state[0][0][1]=1;
}
else

{
now=0;
state[0][0][0]=1;
}

ans=-1;

if (graph[0][0]=='#')
{cout<<-1<<endl;continue;}

if (k>0 && graph[0][0]=='O')
{cout<<-1<<endl;continue;}
DFS(0,0,now,1);
cout<<ans<<endl;
}



return 0;
}
