题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5433
题面:
3 4 4 5 2134 2#23 2#22 2221 1 1 3 3 4 4 7 2134 2#23 2#22 2221 1 1 3 3 4 4 50 2#34 2#23 2#22 2#21 1 1 3 3
1.03 0.00 No Answer
题目大意:
给定起点和终点。有一个意念值k,其实就是可以走k步。每走一步都会产生体力消耗abs(a1-a2)/x,a1,a2分别为两个位置的高度,x为当前剩余意念值。求在限定步数内,从起点到终点到的最小体力消耗。
解题:
之前的代码是错误的,多谢一抹忧伤|指出。深搜理论上不是不可以,但是还需要加一维代表步数,复杂度可能会挺高。故正解是,步数少,且代价低的优先队列配合BFS。
坑点:
当k=0的时候,不管起点和终点是否重合,要直接输出No Answer,好像题面有提及,意念值为0,就意味着失败。
错误代码:
错误原因:
并不是新到达一点时,代价低,就更新该点,可能存在代价低,步数多不能到达的情况,而代价高,步数少,却能到达。
#include<iostream>
using namespace std;
char map[55][55];
double dp[55][55];
int n,m,k,t,sx,sy,dx,dy,dir[4][2]={-1,0,0,1,1,0,0,-1};
bool flag;
void dfs(int x,int y,int step,double cost)
{
int tx,ty;
double tcost;
if(cost>=dp[x][y])return;
else
{
dp[x][y]=cost;
if(x==dx&&y==dy)
{
flag=true;
return;
}
if(step==0)return;
for(int i=0;i<4;i++)
{
tx=x+dir[i][0];
ty=y+dir[i][1];
if(tx>=1&&tx<=n&&ty>=1&&ty<=m&&map[tx][ty]!='#')
{
tcost=cost+1.0*abs(map[x][y]-map[tx][ty])/step;
dfs(tx,ty,step-1,tcost);
}
}
}
}
void init()
{
flag=false;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
dp[i][j]=1e9;
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++)
{
getchar();
for(int j=1;j<=m;j++)
scanf("%c",&map[i][j]);
}
scanf("%d%d%d%d",&sx,&sy,&dx,&dy);
if(k==0)
{
printf("No Answer\n");
continue;
}
init();
dfs(sx,sy,k,0.0);
if(flag)
{
printf("%.2lf\n",dp[dx][dy]);
}
else
printf("No Answer\n");
}
return 0;
}
修改代码:
#include <iostream>
#include <queue>
using namespace std;
char map[55][55];
double dp[55][55][55];
int n,m,k,t,sx,sy,dx,dy,dir[4][2]={-1,0,0,1,1,0,0,-1};
bool flag;
struct node
{
int x,y,step;
double cost;
bool operator<(const node &a)const
{
if(step!=a.step)
return step>a.step;
else
return cost>a.cost;
}
};
priority_queue <node> qe;
void bfs()
{
while(!qe.empty())
qe.pop();
int tx,ty,tstep;
node tmp,cur;
tmp.x=sx,tmp.y=sy,tmp.cost=0.0,tmp.step=0;
qe.push(tmp);
while(!qe.empty())
{
cur=qe.top();
qe.pop();
if(cur.cost>=dp[cur.x][cur.y][cur.step])
continue;
else
{
dp[cur.x][cur.y][cur.step]=cur.cost;
if(cur.x==dx&&cur.y==dy)
{
flag=true;
continue;
}
if(cur.step==k)
continue;
for(int i=0;i<4;i++)
{
tx=cur.x+dir[i][0];
ty=cur.y+dir[i][1];
if(tx>=1&&tx<=n&&ty>=1&&ty<=m&&map[tx][ty]!='#')
{
tmp.x=tx,tmp.y=ty,tmp.step=cur.step+1;
tmp.cost=cur.cost+(1.0*abs(map[cur.x][cur.y]-map[tx][ty])/(k-cur.step));
qe.push(tmp);
}
}
}
}
}
void init()
{
flag=false;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int x=0;x<=k;x++)
dp[i][j][x]=1e9;
}
int main()
{
double ans;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++)
{
getchar();
for(int j=1;j<=m;j++)
scanf("%c",&map[i][j]);
}
scanf("%d%d%d%d",&sx,&sy,&dx,&dy);
if(k==0)
{
printf("No Answer\n");
continue;
}
init();
bfs();
if(flag)
{
ans=dp[dx][dy][0];
for(int i=1;i<=k;i++)
{
if(dp[dx][dy][i]<ans)
ans=dp[dx][dy][i];
}
printf("%.2lf\n",ans);
}
else
printf("No Answer\n");
}
return 0;
}