列表

详情


NC21373. 牛牛的骰子

描述

牛牛有一个N面的骰子A,牛牛很nice的告诉你这个骰子的每个面的数值,现在你需要自己构造一个N面的骰子B,
所有面的之和必须与牛牛的A骰子的总和一样,每个面的数字都是非负整数.要求使得你和牛牛一起掷骰子,让你赢的概率尽可能的大。
牛牛的骰子的每个面的数值不超过5000,你的骰子无限制,只需要总和一样即可

输入描述

第一行输入一个整数n (1 ≤ n ≤ 30)
第二行输入n个整数p[i] (0 ≤ p[i] ≤ 5000)

输出描述

输出n个整数表示B筛子的每个面的数字

示例1

输入:

6
1 2 3 4 5 6

输出:

0 0 0 7 7 7

示例2

输入:

4
0 0 0 2

输出:

0 0 1 1

示例3

输入:

4
1 1 13 1

输出:

4 4 4 4

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 220ms, 内存消耗: 18040K, 提交时间: 2022-01-20 23:47:12

#include<bits/stdc++.h>
using namespace std;
int a[50];
int dp[50][30*5001];
int ny[5005];
int yy[50];
int main()
{
    int n;
    cin>>n;
 ;
    int sum=0;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        sum+=a[i];
    }
  
    for(int i=0;i<=5001;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(i>a[j]) ny[i]++;
        }
    }
    int num=0;
    yy[0]=0;
  
    for(int i=1;i<=5001;i++)
    {
        if(ny[i]!=ny[i-1]) yy[++num]=i;
        
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=sum;j++)
        {
            for(int k=0;k<=num&&yy[k]<=j;k++)
            {
                int z=ny[yy[k]];
               if(j-yy[k]<0) break;
                dp[i][j]=max(dp[i-1][j-yy[k]]+z,dp[i][j]);
            }
        }
    }
    int s=0;
    //cout<<dp[n][sum]<<endl;
    //cout<<dp[n-1][sum-1]<<endl;
    for(int i=1;i<=n;i++)
    {
        if(i==n) {cout<<sum-s<<endl;break;}
        for(int k=0;k<=num&&yy[k]<=sum-s;k++)
        {
           
           int z=ny[yy[k]];
   
          if(dp[n-i+1][sum-s]==dp[n-i][sum-s-yy[k]]+z)
          {
              cout<<yy[k]<<" ";
              s+=yy[k];
              break;
          }
        }
    }
   
  
}

上一题