zoukankan      html  css  js  c++  java
  • [JLOI2013]卡牌游戏

    传送门

    这个题一开始不会转移了……因为自己状态设定的不对。

    应该参考一下约瑟夫问题的操作,设dp[i][j]表示在有i个人的时候从庄家开始数第j个人的获胜概率。这样的话,我们只要枚举每张卡牌,这样的话,每个人获胜的概率就能由有i-1个人的时候推出来,因为其实淘汰一个人就是相当于把队列向前移动几位,但是胜利者并不会改变。

    抽到每张卡的概率相同,所以我们就能得到DP方程:

    dp[i][j] += (dp[i-1][(j-c[k] + i)%i]) / m.

    这样直接递推一下就可以啦,代码很短。注意最后答案要先乘以100.

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<set>
    #include<queue>
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    
    using namespace std;
    typedef long long ll;
    const int M = 10005;
    const ll INF = 1000000009;
    const int mod = 9397;
    
    int read()
    {
        int ans = 0,op = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
        if(ch == '-') op = -1;
        ch = getchar();
        }
        while(ch >= '0' && ch <= '9')
        {
        ans *= 10;
        ans += ch - '0';
        ch = getchar();
        }
        return ans * op;
    }
    
    int a[M],n,m;
    double dp[1005][1005];
    
    int main()
    {
       n = read(),m = read();
       rep(i,1,m) a[i] = read();
       dp[1][1] = 1.0;
       rep(i,2,n)
       rep(j,1,i)
       rep(k,1,m)
       {
          int c = (a[k] % i) ? a[k] % i : i;
          if(c > j) dp[i][j] += dp[i-1][i-c+j] / (double)m * 1.0;
          else if(c < j) dp[i][j] += dp[i-1][j-c] / (double)m * 1.0;
       }
       rep(i,1,n) printf("%.2lf%% ",dp[n][i] * 100.0);enter;
       return 0;
    }
  • 相关阅读:
    约瑟夫问题
    十点半
    鹊桥相会
    C语言实验——数日子
    汉诺塔
    读入字符串
    C语言实验——各位数字之和排序
    数据结构实验之链表五:单链表的拆分
    C语言实验——分割整数
    大一上学期
  • 原文地址:https://www.cnblogs.com/captain1/p/9892848.html
Copyright © 2011-2022 走看看