• 洛谷 P2059 [JLOI2013]卡牌游戏


    题目描述

    N个人坐成一圈玩游戏。一开始我们把所有玩家按顺时针从1到N编号。首先第一回合是玩家1作为庄家。每个回合庄家都会随机(即按相等的概率)从卡牌堆里选择一张卡片,假设卡片上的数字为X,则庄家首先把卡片上的数字向所有玩家展示,然后按顺时针从庄家位置数第X个人将被处决即退出游戏。然后卡片将会被放回卡牌堆里并重新洗牌。被处决的人按顺时针的下一个人将会作为下一轮的庄家。那么经过N-1轮后最后只会剩下一个人,即为本次游戏的胜者。现在你预先知道了总共有M张卡片,也知道每张卡片上的数字。现在你需要确定每个玩家胜出的概率。

    这里有一个简单的例子:

    例如一共有4个玩家,有四张卡片分别写着3,4,5,6.

    第一回合,庄家是玩家1,假设他选择了一张写着数字5的卡片。那么按顺时针数1,2,3,4,1,最后玩家1被踢出游戏。

    第二回合,庄家就是玩家1的下一个人,即玩家2.假设玩家2这次选择了一张数字6,那么2,3,4,2,3,4,玩家4被踢出游戏。

    第三回合,玩家2再一次成为庄家。如果这一次玩家2再次选了6,则玩家3被踢出游戏,最后的胜者就是玩家2.

    输入输出格式

    输入格式:

    第一行包括两个整数N,M分别表示玩家个数和卡牌总数。

    接下来一行是包含M个整数,分别给出每张卡片上写的数字。

    输出格式:

    输出一行包含N个百分比形式给出的实数,四舍五入到两位小数。分别给出从玩家1到玩家N的胜出概率,每个概率之间用空格隔开,最后不要有空格。

    输入输出样例

    输入样例#1:
    输入样例1:
    5 5
    2 3 5 7 11
    输入样例2:
    4 4
    3 4 5 6
    输出样例#1:
    输出样例1:
    22.72%  17.12%  15.36%  25.44%  19.36%
    输出样例2:
    25.00%  25.00%  25.00%  25.00%

    说明

    对于30%的数据,有1<=N<=10

    对于50%的数据,有1<=N<=30

    对于100%的数据,有1<=N<=50 1<=M<=50 1<=每张卡片上的数字<=50

    看懂题目花了半天,我还以为庄家死了才换庄家

    感觉dp特别难写,于是写了记忆化搜索

    复杂度mn^2硬生生被我自己加到mn^3,然后跑了最后一名,改回mn^2之后变成第三

    难度大概在于怎么在printf里输出一个%以及给double memset

    安利这个 http://blog.csdn.net/popoqqq/article/details/38926889

    我们挨个计算每个位置获胜的概率,发现在计算某个位置概率的时候,其他所有位置都是没有区别,所以可以这么dp

    dp[i][j]:现在还剩下i个人,当前正在计算的目标坐在庄家顺时针第j个,他获胜的概率,然后枚举卡片搜索转移即可

    这个dp数组是可以复用的,所有看上去mn^3的复杂度,其实只有mn^2,

    不说了,从0开始标号真是太棒了

     1 #include <iostream>
     2 #include <cstdlib>
     3 #include <cstdio>
     4 #include <algorithm>
     5 #include <string>
     6 #include <cstring>
     7 #include <cmath>
     8 #include <map>
     9 #include <stack>
    10 #include <set>
    11 #include <vector>
    12 #include <queue>
    13 #include <time.h>
    14 #define eps 1e-7
    15 #define INF 0x3f3f3f3f
    16 #define MOD 1000000007
    17 #define rep0(j,n) for(int j=0;j<n;++j)
    18 #define rep1(j,n) for(int j=1;j<=n;++j)
    19 #define pb push_back
    20 #define set0(n) memset(n,0,sizeof(n))
    21 #define ll long long
    22 #define ull unsigned long long
    23 #define iter(i,v) for(edge *i=head[v];i;i=i->nxt)
    24 #define max(a,b) (a>b?a:b)
    25 #define min(a,b) (a<b?a:b)
    26 #define print_runtime printf("Running time:%.3lfs
    ",double(clock())/1000.0)
    27 #define TO(j) printf(#j": %d
    ",j);
    28 //#define OJ
    29 using namespace std;
    30 const int MAXINT = 100010;
    31 const int MAXNODE = 100010;
    32 const int MAXEDGE = 2 * MAXNODE;
    33 char BUF, *buf;
    34 int read() {
    35     char c = getchar(); int f = 1, x = 0;
    36     while (!isdigit(c)) {if (c == '-') f = -1; c = getchar();}
    37     while (isdigit(c)) {x = x * 10 + c - '0'; c = getchar();}
    38     return f * x;
    39 }
    40 char get_ch() {
    41     char c = getchar();
    42     while (!isalpha(c)) c = getchar();
    43     return c;
    44 }
    45 //------------------- Head Files ----------------------//
    46 
    47 int n, m, card[51];
    48 double dp[51][51], odm; //there are i people left in the game, and the current person is the jth person at the clockwise order of the first player
    49 void get_input();
    50 void work();
    51 double dfs(int left, int p) {
    52     double ans = 0;
    53     if (left == 1) return 1.0;
    54     if (dp[left][p] > -eps) return dp[left][p];
    55     rep0(i, m) {
    56         int x, y, pos = card[i] % left;
    57         if (pos == p) continue;
    58         pos = (pos + 1) % left;
    59         ans += odm * dfs(left - 1, (p - pos + left) % left);
    60     }
    61     dp[left][p] = ans;
    62     return ans;
    63 }
    64 int main() {
    65     get_input();
    66     work();
    67     return 0;
    68 }
    69 void work() {
    70     memset(dp, 0xfe, sizeof(dp));
    71     rep0(i, n) {
    72         printf("%.2lf%% ", dfs(n, i) * 100);
    73     }
    74     putchar('
    ');
    75 }
    76 void get_input() {
    77     n = read(); m = read();
    78     odm = 1.0 / m;
    79     rep0(i, m) card[i] = read() - 1;
    80 }
  • 相关阅读:
    leetcode 190 Reverse Bits
    vs2010 单文档MFC 通过加载位图文件作为客户区背景
    leetcode 198 House Robber
    记忆化搜索(DP+DFS) URAL 1183 Brackets Sequence
    逆序数2 HDOJ 1394 Minimum Inversion Number
    矩阵连乘积 ZOJ 1276 Optimal Array Multiplication Sequence
    递推DP URAL 1586 Threeprime Numbers
    递推DP URAL 1167 Bicolored Horses
    递推DP URAL 1017 Staircases
    01背包 URAL 1073 Square Country
  • 原文地址:https://www.cnblogs.com/LoveYayoi/p/6929928.html
Copyright © 2020-2023  润新知