Topcoder SRM579 1000pts

石头剪刀布QAQ

一看是个很油的概率dp

首先一看你很快能得出状态的表示F[i][r][p][s]

然后只要考虑r,p,s出现的次数来进行概率dp就好了

具体实现的时候细节很多(少)

如果预处理一下组合数常数短了一截。但是自信的我认为50^4根本不慌。最后还是过了。

#include<map>
#include<stack>
#include<queue>
#include<cstdio>
#include<string>
#include<vector>
#include<cstring>
#include<complex>
#include<iostream>
#include<assert.h>
#include<algorithm>
using namespace std;
#define inf 1001001001
#define infll 1001001001001001001LL
#define ll long long
#define dbg(vari) cerr<<#vari<<" = "<<(vari)<<endl
#define gmax(a,b) (a)=max((a),(b))
#define gmin(a,b) (a)=min((a),(b))
#define Ri register int
#define gc getchar()
#define il inline
il int read(){
    bool f=true;Ri x=0;char ch;while(!isdigit(ch=gc))if(ch==‘-‘)f=false;while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-‘0‘;ch=gc;}return f?x:-x;
}
#define gi read()
#define ig read()
#define FO(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
int n;double ans,R[55],P[55],S[55];
double dp[55][55][55][55];
int main(){
    FO(rps);
    n=gi;
    for(int i=0;i<n;i++){
        R[i]=gi;R[i]/=300;
        P[i]=gi;P[i]/=300;
        S[i]=gi;S[i]/=300;
    }
    for(int a=0;a<n;a++){
        dp[a][0][0][0]=1.0;
        for(int i=0;i<n;i++)
            for(int j=i;j+1;j--)
                for(int k=i-j;k+1;k--)
                    for(int s=i-j-k;s+1;s--) {
                        if(i!=a){
                        dp[a][j+1][k][s]=dp[a][j+1][k][s]+1.0*(j+k+s+1)/(i+1)*R[i]*dp[a][j][k][s];
                        dp[a][j][k+1][s]=dp[a][j][k+1][s]+1.0*(j+k+s+1)/(i+1)*P[i]*dp[a][j][k][s];
                        dp[a][j][k][s+1]=dp[a][j][k][s+1]+1.0*(j+k+s+1)/(i+1)*S[i]*dp[a][j][k][s];
                        }dp[a][j][k][s]=dp[a][j][k][s]*(1-1.0*(j+k+s)/(i+1));
                    }
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<n-i;j++){
            for(int k=0;k<n-i-j;k++){
                double r,p,s;
                r=p=s=0;
                //face i rock k scissor j paper
                for(int a=0;a<n;a++){
                    double t=dp[a][i][j][k],m=n-i-j-k;
                    r=r+dp[a][i][j][k]/m*R[a];
                    p=p+dp[a][i][j][k]/m*P[a];
                    s=s+dp[a][i][j][k]/m*S[a];
                }
                double tmp=0.0;
                gmax(tmp,3*r+p);
                gmax(tmp,3*p+s);
                gmax(tmp,3*s+r);
                /*
                old version fucking possiblities
                gmax(ans,3*r+p);
                gmax(ans,3*p+s);
                gmax(ans,3*s+r);*/
                ans+=tmp;
            }
        }
    }
    printf("%.9lf",ans);
    return 0;
}
时间: 2024-08-04 05:23:29

Topcoder SRM579 1000pts的相关文章

topcoder 650 srm div2 1000pts

(15) 也是 DIV1 500 题意是给定 一个无向图 删去一条边以后 可不可以是完全二叉树. 细节点很多,开始做法居然求到桥去了,最近强联通写傻了. 最多1024-1个点 1024-1条边枚举 所以: 先枚举要删去的边,然后进行判断. 判断是否是一颗完全二叉树的话 要一个标记deep深度 max deep==h 然后还要看是否整个图强联通 还有一点 点的度 为1 ,2 ,3 其中度为2的只有一个 ,度为1的有2^(h-2)个 code: 1 #include<iostream> 2 #in

Topcoder SRM 603 div1题解

昨天刚打了一场codeforces...困死了...不过赶在睡前终于做完了- 话说这好像是我第一次做250-500-1000的标配耶--- Easy(250pts): 题目大意:有一棵树,一共n个节点,每个节点都有一个权值,两人A和B分别进行操作,由A先手,每人可以选择一条边,将它删掉得到两个联通块.游戏不断进行下去,最后只剩下一个节点.A希望最后的节点权值尽可能大,B希望尽可能小,求这个最后的值.数据保证n<=50. 这道题真的是博弈好题啊-(感觉放到ACM很合适啊) 我们考虑第一次A会如何选

TOPCODER SAM 686 div1 300

// TOPCODER SAM 686 div1 300 Problem Statement 带有小中括号的括号序列,问可以去掉多少子串,使得剩下的非空串是合法的. Constraints 字符串长度不超过 40. Examples // ans[i] = count(s[i]) string s[] = {"()[]", "())", "()()", "([)]", "())[]][]([]()]]()]]]&qu

topcoder srm656 1000分题

Problem Statement   You are given an int N and a int[] pos. We are interested in some permutations of the set {1,2,...,N}. A permutation p is called good if the following condition is satisfied: for each valid k, we have p(k) < p(k+1) if and only if

TopCoder SRM 625 Incrementing Sequence 题解

本题就是给出一个数k和一个数组,包括N个元素,通过每次增加数组中的一个数的操作,最后需要得到1 - N的一个序列,不用排序. 可以从暴力法入手,然后优化. 这里利用hash表进行优化,最终得到时间效率是O(n*n)的算法,而且常数项应该很低,速度还挺快的. 思路: 1 如果数组A[i]在1 -N 范围内,就利用bool B[]记录,这个数已经找到了: 2 如果A[i]的值之前已经找到了,那么就增加k操作,得到新的值A[i]+k,看这个值是否找到了,如果没找到,就使用B记录,如果之前已经找到了,那

Topcoder SRM625 题解

给出一个字符串求是palindrome和anagram的比率是多少. 知识点: 1 DBL_MAX 64位double的最长数大概是1.7E308,很大很大,比long long大上不知多少倍,故此大概能容纳150!的数值,不能容纳200!的数值 2 偶数的时候,不能有字母重复为基数次,否则不能组成palindrome 3 基数的时候,只能有且只有有一个字母重复为基数次,用于放在中间的,否则也不能组成palindrome 4 计算带重复数的全排列公式:P(N) / P(M1)/P(M2)...P

Topcoder SRM 刷题企划

1.本文用来记录自己在Topcoder上刷过的题目.不过重点是记录心得,记录自己的思路问题. 2.刷的题目全部都是Div2 1000分的题目,小概率会去做Div1 的进阶题. 3.基本上自己写出来的题目都不会另开一篇来写. 4.Topcoder使用: [教程1][教程2] SRM 508 Div2 YetAnotherORProblem (Div2 Hard) 题意:构造长度为N,各元素上限为R的序列,并且满足$A_1+A_2+\cdots+A_n=A_1|A_2|\cdots|A_n$,求方案

Topcoder SRM656div1 250 ( 期望DP )

Problem Statement    Charlie has N pancakes. He wants to serve some of them for breakfast. We will number the pancakes 0 through N-1. For each i, pancake i has width i+1 and deliciousness d[i].Charlie chooses the pancakes he is going to serve using t

[topcoder]TheGridDivTwo

http://community.topcoder.com/stat?c=problem_statement&pm=13628&rd=16278 标程是BFS,我用DFS,都可解. 这里复杂的把pair写了hash函数,其实直接用个矩阵来存bool就可以了. #include <vector> #include <algorithm> #include <unordered_set> #include <utility> using name