• c++ 汽车加油行驶问题


    汽车加油行驶问题

    题目描述

    给定一个 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。

    输入

    第一行是 N,K,A,B,C的值。第二行起是一个 N*N 的 0-1 方阵,每行 N 个值,至 N+1 行结束。方阵的第 i 行第 j 列处的值为 1 表示在网格交叉点(i,j)处设置了一个油库,为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
    

    提示

    (none)

    AC代码

    #include <iostream> 
    #include <string.h> 
    using namespace std;
    int n,k,a,b,c;
    int g[101][101];
    struct Point
    {
        int x,y,o,ans;
    };
    int dx[4] = {0,0,1,-1};
    int dy[4] = {1,-1,0,0};
    int dm[4] = {0,1,0,1};//dm是控制回走的时候是否收费 
    int f,e;
    Point q[7000000],s;
    bool used[101][101][11];
    int m[101][101][11];
    int main()
    {
        cin >> n >>k >> a >>b >> c;//n是n行n列的矩阵 k是加满油后能行的路程 a是加油的费用
    	//b是倒退的费用 c造加油站的费用 
        for (int i=1;i <= n;i++)//将矩阵转换为数组 
            for (int j = 1;j <= n;j++)
                scanf("%d",&g[i][j]);//输入 
        s.x= 1,s.y = 1,s.o = k,s.ans = 0;//s.x是起点的x坐标 s.y是起点的y坐标 
    	//s.o就是汽车可以行驶的剩余路程  s.ans是从起点到此地的钱数 
    	memset(used,0,sizeof(used));//memset()把used[][][]全部初始化为0     
    	used[1][1][k] = 1;//把起点标为已经走过,(并记录剩余的路程为k)     
    	m[1][1][k] = 0;//走到这里时一共用的钱数 (并记录剩余的路程为k)  
    	f=1,e=1;//f出队 e入队 
    	q[1]=s;//把s入队     
    	while (f <= e)//防止越界     
    	{
            Point u = q[f++];//u是选中的元素         
    		for (int i = 0;i < 4;i ++)//重复向4个方向拓展         
    		{
                Point v = u;//v是由u拓展而来             
    			v.x = u.x + dx[i];//向4个方向拓展  
    			v.y = u.y + dy[i];//up
                v.o = u.o - 1;//剩余路程 -1 
    			v.ans = u.ans + dm[i] * b;//v.ans是钱数  u.ans + dm[i] * b  是 加上回走的费用
    			//dm[i]是1  , 表示回走 dm[i]是0 表示不回走  
    			if (v.x < 1 || v.x > n || v.y < 1 || v.y > n) continue;//保证这些拓展而来的坐标在棋盘上             
    			if (v.o < 0) continue;//剩余路程 > 0才可以继续行驶             
    			if (g[v.x][v.y] == 1) //如果是加油站 就要加油 
    			{ 
                    v.ans += a;//加上加油费 
    				v.o = k;//重新计算可行驶的路程 
    				if (used[v.x][v.y][v.o] == 0 || (used[v.x][v.y][v.o] == 1 && v.ans < m[v.x][v.y][v.o]))
                    {
                        used[v.x][v.y][v.o] = 1;//把这个点标为走过 
                        m[v.x][v.y][v.o] = v.ans;//把现在的钱数赋值(弄)到总钱数里面 
                        //m[][][]是存储所有点的钱数的数组 
                        //是否可以不用数组的方式,用一个变量每次比较并覆盖 
                        e ++;//e是入队下标 
                        q[e] = v;//把v入队 
                    }
                }
                if (g[v.x][v.y]==0) //如果不是加油站 
                { 
                    if(v.o>=0)//还可以开(还有油) 
                    {
                        if (used[v.x][v.y][v.o] == 0 || (used[v.x][v.y][v.o] == 1 && v.ans < m[v.x][v.y][v.o]))
                        {
                            used[v.x][v.y][v.o] = 1;//已使用 
                            m[v.x][v.y][v.o] = v.ans;//把现在的钱数赋值(弄)到总钱数里面 
                            e ++;//e是入队下标 
                            q[e] = v;//把v入队 
                        }  
                    }
                    v.ans+=a+c,v.o=k;//造加油站  付钱    重新计算可行驶的路程  
                    if (used[v.x][v.y][v.o] == 0 || (used[v.x][v.y][v.o] == 1 && v.ans < m[v.x][v.y][v.o]))
                    {
                        used[v.x][v.y][v.o] = 1;//已使用 
                        m[v.x][v.y][v.o] = v.ans;
                        e ++;
                        q[e] = v;
                    }
                }
            }
        }    
        int res = 1000000000;//把res设成最大,取最小值 
        for (int i = 0;i <= k ;i++)//重复计算 
            if (res > m[n][n][i] && m[n][n][i] != 0) res = m[n][n][i];//取最小值 
        cout << res << endl;//将最后一个点的费用输出(即最小费用) 
        return 0;
    }
    

    (未完待续)

  • 相关阅读:
    python学习笔记Day3
    python学习笔记Day2
    IIS7.5部署除静态页面外都是404的解决方案
    CommandBehavior.CloseConnection有何作用
    没事别老待在家里
    冻结表格行列的思路
    如何构建逻辑清晰的可拖拽树的数据结构
    “仅次于20年前的最好的时间是现在“
    java的静态代理和2种动态代理(未完,待续)
    i++和++i
  • 原文地址:https://www.cnblogs.com/LJA001162/p/11299957.html
Copyright © 2020-2023  润新知