HRBUST 2575 是男人就下100层

文章讨论了一个名为《是男人就下100层》的游戏,玩家需要在给定规则下通过移动浮板获取积分,通过动态规划方法解决在特定条件下到达底层并获取最大积分的问题。
摘要由CSDN通过智能技术生成
《是男人就下100层》
Time Limit: 1000 MSMemory Limit: 32768 K
Total Submit: 13(2 users)Total Accepted: 1(1 users)Rating: ⭐⭐⭐⭐Special Judge: No
Description

王金刚在玩一个《是男人就下100层》的游戏

这个游戏是这样的 

第一层有一块浮板 第二层有二块浮板 ... 第n层有n块浮板

当玩家在第i块浮板上 下一次他只能到达下一层的第i-1块(如果有的话) 或者 第i块或者第i+1块浮板 (类似金字塔形状)

王金刚正在第一层

王金刚想要从第一层走到最底下一层

每一块浮板上都有一个积分 王金刚想获得的积分最大

当然事情没有这么简单 我们会给出几块必须要路过的浮板 

请你输出王金刚走到所有必须路过的浮板并且到达最底层的最多得分

Input

第一行输入T表示T组输入 T<=500

每组样例如下
    第一行输入 n m 表示共n层 m块浮板必须要经过 1<=n<=10 0<=m<=10
    接下来n行 每行包含i个元素 每个元素是该浮板的得分( 0<aij <= 1e9)
    接下来m行 每行输入k v 表示必须到达第k层的v号浮板

Output
输出走到所有必须路过的浮板并且到达最底层 如果不能达成请输出-1 (行末带有换行)
Sample Input
3
10 5

4 5
7 8 6 
3 5 2 4
2 5 6 3 7
5 6 3 7 8 5
1 2 3 5 8 6 4
4 8 9 6 5 8 9 6 
1 2 5 9 8 9 9 9 1
1 3 4 5 6 7 8 1 5 2
1 1
2 1
4 3
6 4
7 3


10 4

4 5
7 8 6 
3 5 2 4
2 5 6 3 7
5 6 3 7 8 5
1 2 3 5 8 6 4
4 8 9 6 5 8 9 6 
1 2 5 9 8 9 9 9 1
1 3 4 5 6 7 8 1 5 2
2 1
2 1
7 5
2 1


10 0

4 5
7 8 6 
3 5 2 4
2 5 6 3 7
5 6 3 7 8 5
1 2 3 5 8 6 4
4 8 9 6 5 8 9 6 
1 2 5 9 8 9 9 9 1
1 3 4 5 6 7 8 1 5 2
 
Sample Output

55

64

65

Source
20231126

由于数据量很小 只限制了1<=n<=10 0<=m<=10 所以可以使用dfs来解决 但是聪明的你并不打算这么做 想用更短的时间来解决问题 万一后台不小心(故意的还是不小心的)扩大了数据范围呢 所以这道题就可以使用dp来做了

现在给出一个简化版本:

有一个三角形,从数组(1,1)的位置出发(初始索引为1,1),向下一行走,只能走到正下方或者右下方的位置,如果走到了该位置,那么你会获得等于该数字大小的分数(初始分数为(1,1)位置的数字的大小),直到走到最后一层,找出你可以获得最大的分数并输出。

输入:
5

3 8
8 1 0
2 7 4 4
4 5 2 6 5
30
输出:
30
Hint:7->3->8->7->5==30

这是一道很简单的dp题目 需要考虑最初的状态 也就是dp[1][1] = a[1][1];,转移也不难想到dp[i][j] = max(dp[i - 1][j - 1], dp[i - 1][j]) + a[i][j]; 那么代码就很好写出来了

/*
 * @author: LANSGANBS
 * @Date: Created - 2023-12-04 14:00:26
 * 写完这道就去原
 */
#include <bits/stdc++.h>
#define endl '\n'
#define buff ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
/*
#pragma GCC optimize ("Ofast")
#pragma GCC optimize ("unroll-loops")
#pragma GCC optimize(3)
*/
using namespace std;
#define ll long long
#define int ll
const int N = 1e3 + 7;
int a[N][N];
int dp[N][N];
int best_score = -1;

void solve()
{
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= i; j++)
        {
            cin >> a[i][j];
        }
    }
    dp[1][1] = a[1][1];
    for (int i = 2; i <= n; i++)
    {
        for (int j = 1; j <= i; j++)
        {
            dp[i][j] = max(dp[i - 1][j - 1], dp[i - 1][j]) + a[i][j];
        }
    }
    for (int i = 1; i <= n; i++)
    {
        best_score = max(best_score, dp[n][i]);
    }
    cout << best_score << endl;
    // wout <<L" "<<endl;
    // cout << R"( )" << endl;
}

signed main()
{
    // setlocale(LC_ALL, "");
    buff;
    int t = 1;
    //	cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}
/*
 * @LastEditTime:2023-12-04 14:10:18
 */

这道题弄懂之后 那么最初的问题也就很好想出了 最初的问题不过是可以向左下方走 而且多了几个必须走的位置

/*
 * @author: LANSGANBS
 * @Date: Created - 2023-12-04 13:59:30
 * 写完这道就去原
*/
#include <bits/stdc++.h>
#define endl '\n'
#define buff ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
/*
#pragma GCC optimize ("Ofast")
#pragma GCC optimize ("unroll-loops")
#pragma GCC optimize(3)
*/
using namespace std;
#define ll long long
#define int ll
int T;
int n, m;
int arr[15][15];
int must_arrive[15];

void solve()
{
    cin >> T;
    while (T--)
    {
        cin >> n >> m;
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= i; j++)
            {
                cin >> arr[i][j];
            }
            must_arrive[i] = -1;
        }
        int mark = 0;
        for (int i = 1; i <= m; i++)
        {
            int k, v;
            cin >> k >> v;
            if (must_arrive[k] != -1 && must_arrive[k] != v)
            {
                mark = 1;
            }
            must_arrive[k] = v;
        }
        if (mark == 1)
        {
            cout << -1 << endl;
            continue;
        }
        long long dp[15][15] = {0};
        for (int i = 1; i <= n; i++)
        {
            if (must_arrive[n] == -1 || must_arrive[n] == i)
            {
                dp[n][i] = arr[n][i];
            }
            else
            {
                dp[n][i] = -1;
            }
            dp[i][0] = -1;
            dp[i][i + 1] = -1;
        }
        for (int row = n - 1; row >= 1; row--)
        {
            for (int col = 1; col <= row; col++)
            {
                if (must_arrive[row] == -1 || must_arrive[row] == col)
                {
                    int best_score = -1;
                    for (int i = -1; i <= 1; i++)
                    {
                        if (dp[row + 1][col + i] > best_score)
                        {
                            best_score = dp[row + 1][col + i];
                        }
                    }
                    if (best_score == -1)
                    {
                        dp[row][col] = -1;
                    }
                    else
                    {
                        dp[row][col] = best_score + arr[row][col];
                    }
                }
                else
                {
                    dp[row][col] = -1;
                }
            }
        }
        cout << dp[1][1] << endl;
    }
    // wout <<L" "<<endl;
    // cout << R"( )" << endl;
}

signed main()
{
    // setlocale(LC_ALL, "");
    buff;
    int t = 1;
    //	cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}
/*
 * @LastEditTime: 2023-12-04 14:51:59
*/

  • 20
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值