SWUN 1076 - 中州之旅

22 篇文章 0 订阅


中州之旅

时间限制(普通/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
0 0 0
0 0 0
0 0 0
9 3 2 3 6
0 0 0 0 1 0 0 0 0 
0 0 0 1 0 1 1 0 0 
1 0 1 0 0 0 0 1 0 
0 0 0 0 0 1 0 0 1 
1 0 0 1 0 0 1 0 0 
0 1 0 0 0 0 0 1 0 
0 0 0 0 1 0 0 0 1 
1 0 0 1 0 0 0 1 0 
0 1 0 0 0 0 0 0 0  

样例输出

12
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;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值