zoukankan      html  css  js  c++  java
  • 汽车加油行驶(cogs 737)

    «问题描述:
    给定一个N*N 的方形网格,设其左上角为起点◎,坐标为(1,1),X 轴向右为正,Y
    轴向下为正,每个方格边长为1,如图所示。一辆汽车从起点◎出发驶向右下角终点▲,其
    坐标为(N,N)。在若干个网格交叉点处,设置了油库,可供汽车在行驶途中加油。汽车在
    行驶过程中应遵守如下规则:
    (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。

    设计一个算法,求出汽车从起点出发到达终点的一条所付费用最少的行驶路线。

    «编程任务:
    对于给定的交通网格,计算汽车从起点出发到达终点的一条所付费用最少的行驶路线。
    «数据输入:
    由文件trav.in提供输入数据。文件的第一行是N,K,A,B,C的值。第二行起是一
    个N*N 的0-1 方阵,每行N 个值,至N+1 行结束。方阵的第i 行第j 列处的值为1 表示在
    网格交叉点(i,j)处设置了一个油库,为0 时表示未设油库。各行相邻两个数以空格分隔。
    «结果输出:
    程序运行结束时,将最小费用输出到文件trav.out中。
    输入文件示例 输出文件示例
    trav.in
    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

    trav.out

    12

    /*
        分层图最短路。
        这个题目看上去很难处理,是因为它有很多限制条件,如果我们把这些限制条件去除之后,就变成了单纯求最短路。
        至于这些条件,我们可以再跑最短路的时候分类讨论。
        如果当前没有油了,就要加油;如果当前有油,就可以前往四周的地方。
        然后再做最短路的时候可以加一维,表示当前的油量,多出来的一维可以用分层图最短路来实现。 
    */
    #include<iostream>
    #include<cstdio>
    #include<queue>
    #define N 1000010
    #define inf 1000000000
    using namespace std;
    int head[N],dis[N],inq[N],map[110][110],vc[2],n,K,A,B,C,S,cnt;
    int dx[4]={0,-1,0,1};
    int dy[4]={-1,0,1,0};
    struct node{int v,w,pre;}e[N*6];
    queue<int> q;
    void add(int u,int v,int w){
        e[++cnt].v=v;e[cnt].w=w;e[cnt].pre=head[u];head[u]=cnt;
    }
    int id(int k,int i,int j){return k*n*n+(i-1)*n+j;}
    void spfa(){
        for(int i=0;i<=id(K,n,n);i++) dis[i]=inf;
        dis[S]=0;q.push(S);
        while(!q.empty()){
            int u=q.front();q.pop();inq[u]=0;
            for(int i=head[u];i;i=e[i].pre)
                if(dis[e[i].v]>dis[u]+e[i].w){
                    dis[e[i].v]=dis[u]+e[i].w;
                    if(!inq[e[i].v]){
                        inq[e[i].v]=1;
                        q.push(e[i].v);
                    }
                }
        }
    }
    int main(){
        freopen("trav.in","r",stdin);
        freopen("trav.out","w",stdout);
        scanf("%d%d%d%d%d",&n,&K,&A,&B,&C);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                scanf("%d",&map[i][j]);
        S=id(K,1,1);vc[0]=C;
        for(int k=0;k<=K;k++)
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++){
                    int tmp=id(k,i,j);
                    if(!k) {add(tmp,id(K,i,j),A+vc[map[i][j]]);continue;}
                    for(int d=0;d<4;d++){
                        int x=i+dx[d],y=j+dy[d];
                        if(x<1||x>n||y<1||y>n) continue;
                        if(d<2){
                            if(map[x][y]) add(tmp,id(K,x,y),A+B);
                            else add(tmp,id(k-1,x,y),B);
                        }
                        else {
                            if(map[x][y]) add(tmp,id(K,x,y),A);
                            else add(tmp,id(k-1,x,y),0);
                        }
                    }
                    if(k<K) add(tmp,id(K,i,j),A+vc[map[i][j]]);
                }
        spfa();
        int ans=inf;
        for(int i=0;i<=K;i++)
            ans=min(ans,dis[id(i,n,n)]);
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    java学习day16--常用类之包装类
    String、StringBuffer、StringBuilder的异同
    java学习day15--常用类之字符串相关的类
    java学习day15--Arrays工具类
    java学习day14--二维数组
    java学习day14--可变长参数
    java学习day13--数组
    java学习day13--自定义异常类
    java学习day12--异常
    接口和抽象类的异同
  • 原文地址:https://www.cnblogs.com/harden/p/6711182.html
Copyright © 2011-2022 走看看