TopCoder-SRM637-DIV1-250pt-GreaterGame-集合+概率

首先容易想到的是把那些已知的轮次尽可能的赢下来。对于已知但赢不下来的,可以放上当前最小的牌,这样能使期望最大。

然后就得到了我们当前的一手牌,和他们当前的一手牌。在已知牌的数字,但是不知牌的顺序的情况下,求得分的期望。

一开始试图用递归的方法去做,发现没办法很好的归纳出已经用了那些牌还剩那些牌。

最后猜测了一种方案,竟然有效:

枚举所有我们的牌和他们的牌,两个一组比较大小。最后用我们大于他们的个数除以总的比较次数,这样得到的结果作为概率,乘上这些剩下的牌数作为期望。再加上必胜的那些牌,就得到了正确答案。

我也不知这个如何证明,且等答案吧。

int n,m;
class GreaterGame
{
        public:
        vector<int> h;
        vector<int> so;
        vector<bool> som;
        vector<bool> sum;
        double calc(vector <int> hand, vector <int> sothe)
        {
            h=hand;so=sothe;
            n=h.size();
            som.resize(MAX_N*2+1,0);
            sum.resize(MAX_N*2+1,0);
            for(int i=0;i<n;i++){
                sum[h[i]-1]=1;
            }
            for(int i=0;i<2*n;i++){
                if(!sum[i]) som[i]=1;
            }
            int mustWin=0;
            int known=0;
            for(int i=0;i<n;i++){
                if(so[i]!=-1){
                    known++;
                    int sun=so[i]-1;
                    bool found=false;
                    som[sun]=false;
                    for(int j=sun+1;j<2*n;j++){
                        if (sum[j]) {
                            sum[j]=false;
                            mustWin++;
                            found=true;
                            break;
                        }
                    }
                    if (!found){
                        for(int j=0;j<2*n;j++){
                            if (sum[j]) {
                                sum[j]=false;
                                break;
                            }
                        }
                    }
                }
            }
            int x=0,y=0;
            for(int i=0;i<2*n;i++) for(int j=0;j<2*n;j++){
                if (sum[i] &&som[j]){
                    if (i>j) x++;
                    y++;
                }
            }
            if ((n-known)==0) return mustWin;
            return (double(x)/double(y))*(n-known)+mustWin;
        }
};
时间: 2024-10-11 19:42:28

TopCoder-SRM637-DIV1-250pt-GreaterGame-集合+概率的相关文章

TopCoder 603 div1 &amp; div2

div2 250pts MiddleCode 题意:s串长度为奇数时,将中间字符取掉并添加到t末尾:长度为偶数时,将中间两个较小的字符取掉并添加到末尾. 分析:直接做,学习了一下substr(s, pos, len)返回s中从pos开始的长度为len的字串. 代码: 1 class MiddleCode { 2 public: 3 void Remove(string &s, int pos) { 4 int len = s.size(); 5 string t = ""; 6

TopCoder SRM500 Div1 250 其他

原文链接https://www.cnblogs.com/zhouzhendong/p/SRM500-250.html SRM500 Div1 250 题意 (看题用了半个小时--) 有 n 个人(编号从 0 到 n-1)玩游戏,要通过投票的方式确定谁输.现在已知有一些人有明确的意见,认为谁输.具体地用一个 vector decision 来描述,vector decision 的大小可能不足 n . 定义一个集合 S 包含一些人,初始的时候集合 S 包含所有人.他们会进行若干轮投票,每一轮中,一

TopCoder 649 div1 &amp; div2

最近一场TC,做得是在是烂,不过最后challenge阶段用一个随机数据cha了一个明显错误的代码,最后免于暴跌rating,还涨了一点.TC题目质量还是很高的,非常锻炼思维,拓展做题的视野,老老实实补题吧. div2 250pts 题意:判断s去掉一个字符后能否和t一样. 代码: 1 class DecipherabilityEasy { 2 public: 3 string check(string s, string t) { 4 int n = s.size(); 5 int m = t

TopCoder SRM420 Div1 500pt RedIsGood

桌面上有R 张红牌和B 张黑牌,随机打乱顺序后放在桌面上,开始一张一张地翻牌,翻到红牌得到1 美元,黑牌则付出1 美元.可以随时停止翻牌,在最优策略下平均能得到多少钱. R,B ≤ 100000. 输入格式: 若干行,每行两个整数R,B 输出格式: 一个实数期望值. 样例输入: 68 7 样例输出 61.103 分析:这道题加深了我对期望+dp的理解.考虑dp,设f[i][j]表示还剩下i张红牌j张黑牌的期望值,这个时候如果停止翻牌,那么f[i][j] = 0,如果继续翻牌,就有i/i+j的概率

topcoder SRM712 Div1 LR

题目: Problem Statement      We have a cyclic array A of length n. For each valid i, element i-1 the left neighbor of element i. Additionally, element n-1 is the left neighbor of element 0. You are given two vector<long long>s s and t, each with n ele

TopCoder SRM502 Div1 500 贪心 01背包

原文链接https://www.cnblogs.com/zhouzhendong/p/SRM502-500.html SRM502 Div1 500 好题. 首先,如果已经确定了解决所有问题的优先级,只需要对于每一个问题是否被解决做出决策,那么显然直接 01 背包就好了. 事实上,我们是可以贪心地确定两个问题的优先程度的. 对于两个问题,假设分别为 a 和 b,则先做 a 再紧接着做 b 和先做 b 再紧接着做 a 的收益之差为 \[ \begin{eqnarray*} &&(-dec_a

TopCoder SRM502 Div1 1000 动态规划

原文链接https://www.cnblogs.com/zhouzhendong/p/SRM502-1000.html SRM502 Div1 1000 题意 从 [0,n-1] 中选择 k 个不同的整数,使得他们的和是 n 的倍数,求方案数.对 \(10^9+7\) 取模. \(n\leq 10^9,k\leq 1000\) 题解 ? 首先我们考虑从 n 个里面选择 k 个并进行排列的方案数,最终只需要除以 k! 就好了. ? 设 \(M=n\) : ? 设 \(f(n,m,t)\) 表示 在

Topcoder SRM646 div1 600 bfs+剪枝

因为只有47个blocks,所以现在小范围内,即在-50 <= x <= 50,-50 <= y <= 50内进行bfs,之后尽量让点向右走,记录最大值. #include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <queue> #include <cm

Topcoder SRM655 DIV1 500 Nine

题意:这题是http://www.cnblogs.com/zyue/p/4436075.html 这题的加强版. 解题思路:根据dp规则,我们可以把d[i]值相同的放到一起,然后算一个总的DP就行了. 解题代码 1 // BEGIN CUT HERE 2 /* 3 4 */ 5 // END CUT HERE 6 /*#line 7 "Nine.cpp" 7 #include <cstdlib> 8 #include <cctype> 9 #include &l

[TopCoder SRM420 Div1 500pt RedIsGood]【数学期望】【动态规划】

[题意] 桌面上有R 张红牌和B 张黑牌,随机打乱顺序后放在桌面上,开始一张一张地翻牌,翻到红牌得到1 美元,黑牌则付出1 美元.可以随时停止翻牌,在最优策略下平均能得到多少钱. [思路]: 于是dp[0][0]=0 dp[i][j]=F[i-1][j]+1;     (j=0) dp[i][j]=0;               (i=0) dp[i][j]= max(0.0,(dp[i-1][j]+1)*(i/(i+j))  +  (dp[i][j-1])*(j/(i+j))); 最后dp[