首页 > 试题广场 >

猿宝猜数字

[编程题]猿宝猜数字
  • 热度指数:127 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
猿宝最近在玩一个猜数字游戏,给定一个数字n,表示答案在1到n之间,每次可以猜一个数字,猜中游戏胜利,但如果猜错了,将要花费所猜数字的金币,并得知是猜大了还是猜小了,但是有k次机会可以免除此花费猿宝想知道,至少需要准备多少金币能确保获得游戏胜利。


输入描述:
输入两个以空格分割的正整数n k。(n<=300,k<=20)


输出描述:
输出一个正整数表示小明需要准备的金币个数。
示例1

输入

3 0

输出

2

说明

先猜数字2,如果答案是2,获得胜利,如果返回猜小了,下次猜1 必定胜利。如果猜大了,下次猜3必定胜利。 
示例2

输入

3 1

输出

0

说明

先猜数字2,并且使用1次不花费金币的特权,这个时候如果答案是2,获得胜利,如果返回猜小了,只剩下1没猜,下次必定胜利。如果猜大了,只剩下3没猜,下次必定胜利。 

备注:
使用python运行超时的考生可以尝试切换使用pypy
区间DP,转移的时候注意子问题分为用了机会和没用机会
#include <bits/stdc++.h>
using namespace std;

int n, m, dp[305][305][25];
int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) {
        for (int j = 0; j <= m; j++) {
            dp[i][i][j] = 0;
            dp[i][i - 1][j] = 0;
        }
    }
    for (int t = 0; t <= m; t++) { //用了几次机会
        for (int i = n; i >= 1; i--) { //L
            for (int j = i + 1; j <= n; j++) { //R
                dp[i][j][t] = 0x3f3f3f3f;
                for (int k = i; k <= j; k++) { //猜k
                    int tmp1 = max(dp[i][k - 1][t], dp[k + 1][j][t]) + k;
                    dp[i][j][t] = min(dp[i][j][t], tmp1);
                    if (t) {
                        int tmp2 = max(dp[i][k - 1][t - 1], dp[k + 1][j][t - 1]);
                        dp[i][j][t] = min(dp[i][j][t], tmp2);
                    }
                    
                }
            }
        }
    }
    printf("%d\n", dp[1][n][m]);

    return 0;
}


发表于 2021-08-16 13:23:28 回复(0)

问题信息

上传者:小小
难度:
1条回答 1745浏览

热门推荐

通过挑战的用户