首页 > 试题广场 >

抽牌

[编程题]抽牌
  • 热度指数:884 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
桌上放了一堆牌,牌从上到下由 1 到 n 编号,每张牌上写有一个数字,第 i 张牌上的数字为 ai,小明和小方在玩轮流取牌的游戏,每次每个人只能取一张牌,小明先取牌。
取牌规则如下,当一个人取牌时,他只能取当前牌堆中的最上面的一张或者最下面一张。小明和小方都采用随机取牌的策略,小明每次以概率 p 取最上面一张牌,以概率 1-p 取最下面一张牌;小方每次以概率 q 取最上面一张牌,以概率 1-q 取最下面一张牌。
最后两人的得分为他们各自取到排上的数字之和。问小明得分的数学期望。

数据范围: , 


输入描述:
第一行输入三个整数 n , P , Q。小明取最上面一张牌的概率 p=P/100 ,小方取最上面一张牌的概率 q=Q/100。
接下来一行 n 个数,每张牌上的数字。


输出描述:
输出答案,四舍五入保留三位小数。
示例1

输入

2 10 90
1 2

输出

1.900
示例2

输入

5 10 20
1 3 4 5 13

输出

18.038
#include <bits/stdc++.h>
using namespace std;

int main(){
    int n, P, Q;
    scanf("%d%d%d", &n, &P, &Q);
    int a[n];
    for(int i=0;i<n;i++)
        scanf("%d", &a[i]);
    double p=P/100.0, q=Q/100.0, dp[n][n];
    memset(dp, 0, sizeof(dp));
    for(int i=0;i<n;i++){
        dp[i][i] = a[i];
        if(i<n-1)
            dp[i][i+1] = p*a[i] + (1-p)*a[i+1];
    }
    for(int k=2;k<n;k++)
        for(int i=0;i<n-k;i++){
            int j=i+k;
            double px = a[i] + q*dp[i+2][j] + (1-q)*dp[i+1][j-1];
            double py = a[j] + q*dp[i+1][j-1] + (1-q)*dp[i][j-2];
            dp[i][j] = p*px + (1-p)*py;
        }
    printf("%.3f\n", dp[0][n-1]);
    return 0;
}

发表于 2020-09-12 13:41:41 回复(0)
更多回答
arr = [int(_) for _ in input().split()]
n, P, Q = arr[0], arr[1], arr[2]
p, q = P / 100, Q / 100
arr = [int(_) for _ in input().split()]
dp = [[0] * n for _ in range(n)]


def func(begin: int, end: int):
    if begin == end:
        dp[begin][end] = arr[begin]
        return
    elif end - begin == 1:
        dp[begin][end] = p * arr[begin] + (1 - p) * arr[end]
        return
    # 甲顶乙顶 选择概率 *(本次选择得分+之前得分)
    # 甲顶乙底
    # 甲底乙顶
    # 甲底乙底
    dp[begin][end] = (
        p * q * (arr[begin] + dp[begin + 2][end])
        + p * (1 - q) * (arr[begin] + dp[begin + 1][end - 1])
        + (1 - p) * q * (arr[end] + dp[begin + 1][end - 1])
        + (1 - p) * (1 - q) * (arr[end] + dp[begin][end - 2])
    )


for gap in range(n):
    for start in range(n):
        end = start + gap
        if end < n:
            func(start, end)
            # print(start, end, end='\t')
        else:
            break
    # print()
print("{:.3f}".format(dp[0][n - 1]))

发表于 2023-03-17 18:13:05 回复(0)
#include <iostream>
#include <vector>
#import <random>
using namespace std;

int main()
{
    int n, P, Q;
    cin>>n>>P>>Q;
    double p = P*1.0/100;
    double q = Q*1.0/100;
    vector<double> nums(n, 0);
    for(int i=0;i<n;i++)
        cin>>nums[i];
    vector<vector<double>> dp(n+2, vector<double>(n+2, 0));
    for(int i=1;i<=n;i++)
        dp[i][i]= nums[i-1];
    for(int k=2;k<=n;k++)
        for(int i=1,j=k;i<=n&&j<=n;i++,j++)
        {
            double left = nums[i-1]+q*dp[i+2][j]+(1-q)*dp[i+1][j-1];
            double right = nums[j-1]+q*dp[i+1][j-1]+(1-q)*dp[i][j-2];
            dp[i][j] = p*left+(1-p)*right;
        }
    printf("%.3f", dp[1][n]);
}

发表于 2020-08-10 22:38:07 回复(0)
为什么本地ide不报数组越界,这上面就报啊?
发表于 2019-04-14 22:08:12 回复(2)

问题信息

难度:
6条回答 1596浏览

热门推荐

通过挑战的用户

查看代码