中州之旅
时间限制(普通/Java) : 1000 MS/ 3000 MS 运行内存限制 : 65536 KByte
总提交 : 27 测试通过 : 12 描述
为了庆祝《斗破苍穹》的完结,YB,CJ和ZJN决定去中州旅行。但途中会经过可怕黑角域, 黑角域由N*N的方形网格组成,设其左上角为起点◎,坐标为(1,1),X 轴向右为正,Y轴向下为正,每个方格边长为1。 如下图所示,三人驾驶的汽车从起点◎出发,驶向右下角终点的中州入口▲,其坐标为(N,N) 。在若干个网格交叉点处,有加油站(用●代表),可供汽车在行驶途中加油。
黑角域中有形形色色的各种规矩,稍有不慎,就会引来杀身之祸。虽然YB的武艺高强,但是出于对CJ 和ZJN的安全考虑,YB决定遵守这些规则。 其中,汽车在黑角域行驶过程中应遵守如下规则: (1)汽车只能沿网格边行驶,装满油后能行驶 K 条网格边。出发时汽车已装满汽油,在起点与终点处不设加油站。 (2)汽车经过一条网格边时,若其X 坐标或 Y 坐标减小,则应付费用B,否则免付费用。 (3)若汽车在行驶过程中遇加油站则必须加满油,并付固定的加油费用A。 (4)在需要时可在任意网格点处增设加油站,并付增设加油站的费用C(不含加油费用A)。 (5)(1)~(4)中的各数N、K、A、B、C均为正整数,且满足约束:2 <= N <= 100,2 <= K <= 10, 1 <= A, B, C <= 150。 由于最近的股市行情很不好,三人的财力都很吃紧,因此他们希望能走费用最小的路线。 输入
单组测试数据 第一行是 N,K,A,B,C的值。 第二行起是一个 N*N 的 0-1 方阵,每行 N 个值,至 N+1 行结束。方阵的第 i 行第 j 列处的值为 1 时表示在网格交叉点(i,j)处设置了加油站,为0 时表示未设加油站。各行相邻两数以空格分隔。 输出
输出从起点到终点的最小费用 样例输入 3 1 1 2 3 样例输出 12 题目来源 YB |
题目地址: http://218.194.91.48/acmhome/problemdetail.do?&method=showdetail&id=1076
比较好的搜索练手题。
第一次做这题的时候,一直WA,没出。
时隔N久之后,再做,还是WA,还好只是WA了3小时,一步步手算数据,终于找到错误了。
。。。 原来我很囧的用地图来记录状态。 结果队列前面的元素走过后,此状态更新。而后面同状态的队列元素再走时,却沿用了新状态。
。。。 这种错不手算,真心难找。。。 以后遇错不能再偷懒只查代码和算法了。。。
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
int n,k,a,b,c;
int map[110][110];
int step[110][110][12];
// 剩余K步不同时,不能相互覆盖 ,过去是这个错,现在还是这个错,查了3小时,谨记、
struct point{
int x,y,k;
}que[440000];
int fx[][2]={{-1,0},{0,-1},{1,0},{0,1}};
int bfs(){
int i,j,s,t,nstep,mx;
point now,next;
memset(step,-1,sizeof(step));
now.x=0,now.y=0,now.k=k;
que[s=t=0]=now;
step[0][0][k]=0;
n--;
c+=a;
mx=100000000;
while(s<=t){
now=que[s%400000];
s++;
for(i=0;i<4;i++){
next.x=now.x+fx[i][0];
next.y=now.y+fx[i][1];
if(next.x<0 || next.x>n || next.y<0 || next.y>n) continue;
nstep=step[now.x][now.y][now.k];
if(next.x==n && next.y==n)
mx=mx<nstep?mx:nstep;
if(i<2) nstep+=b;
if(map[next.x][next.y]){
nstep+=a;
next.k=k;
}
else{
next.k=now.k-1;
if(next.k<=0){
next.k=k;
nstep+=c;
}
}
if(next.k==0) cout<<"1"<<endl;
if(step[next.x][next.y][next.k]!=-1)
if(nstep>=step[next.x][next.y][next.k])
continue;
step[next.x][next.y][next.k]=nstep;
t++;
que[t%400000]=next;
}
}
return mx;
}
int main(){
int i,j;
while(~scanf("%d%d%d%d%d",&n,&k,&a,&b,&c)){
for(i=0;i<n;i++)
for(j=0;j<n;j++)
scanf("%d",&map[i][j]);
printf("%d\n",bfs());
}
return 0;
}