编程题目--救火英雄

印象中的题目描述:总共10个位置,每一秒在不同位置上出现NPC,玩家去接住NPC来得分。玩家每秒只能左移一格或右移一格或保持不动。
输入:第一行是NPC个数,接下来每行有三个元素,第1个元素表示在第几秒,第2个元素表示NPC所在位置,第3个元素表示NPC的分值。
输出:可获得的最大分值和路径,路径多个时任取一个。实现这个游戏。
补充:玩家有一个在第0秒的初始位置。
例如:
初始位置为3
输入:
3
1 3 1
2 1 1
3 5 3
则可获得最大分为4,玩家位移为3->4->5
此题类似于动态规划里的数塔问题。
关键是在分析时要自底向上来计算比较简便。
设在第i行第j位置。设f[i][j][1]上的元素表示在这个位置能取得的最大总分。
此位置能得到的最大分数为第i+1行的j-1、j、j+1这三个位置上的f 的最大值。即max(f[i+1][j-1][1],f[i+1][j][1],f[i+1][j+1][1])。
最后逆推计算到第一行,每个初始位置能获得的最大分值就都算出来了。
这里规定中间数最大且与左右相等取中间位置,左右相等取右。
代码如下:

#include<iostream>
#include <vector>
using namespace std;
int main(){
    int N;
    cout<<"请输入: "<<endl;
    cin>>N;
    if(N<1){
        cout<<"请输入正确的NPC数目"<<endl;
        return 0;//退出程序
    }   
    //使用vector来实现动态数组
    vector<vector <int> > Inputs(N,vector<int> (3));
    for(int i=0;i<N;i++){
        cin>>Inputs[i][0]>>Inputs[i][1]>>Inputs[i][2];
    }

    int m=Inputs[N-1][0]+1;//取输入里最后一行的第一个元素,表示总共几秒,加1是用0行来表示初始位置//若玩了3秒,则矩阵有4行。

    int LOC=10;//10个位置
    int n=LOC+2;//多2列是用第一列和第二列来保证后面计算时的边界的特殊情况不用多考虑

    //这样矩阵是有12列
    //shuta矩阵行表示在第几秒,列表示位置,
    vector<vector<vector<int> > >shuta(m,vector<vector<int> > (n,vector<int> (3) ) );
    //矩阵第三维[0]的元素表示分值,在代码中不参加计算,[1]的元素表示f,即从这个位置开始能得到的最大分值,[2]的元素表示位移-1或0或+1
    for(int i=0;i<m;i++){
        for(int j=0;j<n;j++){
            for(int k=0;k<3;k++){
                shuta[i][j][k]=0;//矩阵初始化为0
            }
        }
    }
    for(int i=0;i<N;i++){
        shuta[Inputs[i][0]][Inputs[i][1]][0]=Inputs[i][2];//在矩阵中相应位置加入分值
        shuta[Inputs[i][0]][Inputs[i][1]][1]=Inputs[i][2];//同样加入分值,第三维上的[1]在后面的计算要使用到
    }
    for(int i=m-2;i>=0;i--){//从倒数第二行开始 注意:最后一行下标为m-1,所以倒数第二行为m-2
        for(int j=1;j<n-1;j++){
            //可能取三种情况
            //应该比较的是动态规划的结果而不是分值
            if(shuta[i+1][j-1][1]<=shuta[i+1][j][1] && shuta[i+1][j][1]>=shuta[i+1][j+1][1]){
                shuta[i][j][1]+=shuta[i+1][j][1];
                shuta[i][j][2]=0;
            }
            else if(shuta[i+1][j-1][1]>shuta[i+1][j][1] &&  shuta[i+1][j-1][1]>shuta[i+1][j+1][1]){
                shuta[i][j][1]+=shuta[i+1][j-1][1];
                shuta[i][j][2]=-1;//左移
            }
            else{
                shuta[i][j][1]+=shuta[i+1][j+1][1];//包含左右相等的情况
                shuta[i][j][2]=1;
            }
        }
    }
    int Locate;
    cout<<"请输入初始位置: "<<endl;
    cin>>Locate;
    if(Locate<1 || Locate >10){
        cout<<"请输入正确的初始位置!"<<endl;
        return 0;
    }
    cout<<"在初始位置为 "<<Locate<<" 时,结果为:"<<shuta[0][Locate][1]<<endl;//输出结果
    cout<<"路径为(第一个数字表示初始位置):"<<Locate;
    for(int i=0;i<m-1;i++){
        Locate+=shuta[i][Locate][2];
        cout<<"->"<<Locate;
    }

}

上面代码可能存在的问题:
对于各种无效非法输入的检测没有考虑到所有情况,比如英文字母特殊字符;
对于输入的矩阵也没有做检测。比如 :
9 2 1
1 2 3
导致下面的秒数比上面小,不合游戏设计同时在代码中会产生错误。
矩阵的输入位置也要检测是不是在1到10之间。
起始位置的输入也要在1到10之间。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值