[DP 博弈] Topcoder SRM579 Div1. RockPaperScissors

每一轮的策略跟之前出现过的剪刀石头布的数量有关

fi,a,b,c f i , a , b , c 表示之前出现了 a a 次石头, b 次剪刀 , c c 次布,然后第 i 个筛子没用过的概率

DP一下,每一轮独立算贡献

// BEGIN CUT HERE  

// END CUT HERE  
#include <vector>  
#include <list>  
#include <map>  
#include <set>  
#include <deque>  
#include <stack>  
#include <bitset>  
#include <algorithm>  
#include <functional>  
#include <numeric>  
#include <utility>  
#include <sstream>  
#include <iostream>  
#include <iomanip>  
#include <cstdio>  
#include <cmath>  
#include <cstdlib>  
#include <ctime>  
#include <queue>
#include <assert.h>
#include <cstring>  
#define pb push_back
#define fi first
#define se second

using namespace std;  

const int N=51;

int n;
double a[N],b[N],c[N],f[N][N][N][N],C[N][N];

class RockPaperScissors{  
public:  
  double bestScore(vector <int> Aa, vector <int> Bb, vector <int> Cc) {  
    n=Aa.size();
    for(int i=1;i<=n;i++) a[i]=Aa[i-1];
    for(int i=1;i<=n;i++) b[i]=Bb[i-1];
    for(int i=1;i<=n;i++) c[i]=Cc[i-1];
    for(int i=0;i<=n;i++){
      C[i][0]=1;
      for(int j=1;j<=i;j++)
    C[i][j]=C[i-1][j]+C[i-1][j-1];
    }
    memset(f,0,sizeof(f));
    double ans=0;
    for(int i=1;i<=n;i++){
      f[i][0][0][0]=1;
      for(int j=1;j<=n;j++){
    if(j==i) continue;
    for(int t=j;t;t--){
      for(int x=0;x<=t;x++)
        for(int y=0;x+y<=t;y++){
          int z=t-x-y;
          if(x) f[i][x][y][z]+=f[i][x-1][y][z]*a[j]/300;
          if(y) f[i][x][y][z]+=f[i][x][y-1][z]*b[j]/300;
          if(z) f[i][x][y][z]+=f[i][x][y][z-1]*c[j]/300;
        }
    }
      }
      for(int x=0;x<=n-1;x++)
    for(int y=0;x+y<=n-1;y++)
      for(int z=0;x+y+z<=n-1;z++)
        f[i][x][y][z]/=C[n][x+y+z];
    }
    for(int x=0;x<=n-1;x++)
      for(int y=0;x+y<=n-1;y++)
    for(int z=0;x+y+z<=n-1;z++){
      int r=n-x-y-z;
      double pa=0,pb=0,pc=0;
      for(int i=1;i<=n;i++){
        pa+=f[i][x][y][z]*a[i]/300;
        pb+=f[i][x][y][z]*b[i]/300;
        pc+=f[i][x][y][z]*c[i]/300;
      }
      pa/=r; pb/=r; pc/=r;
      ans+=max(3*pa+pb,max(3*pb+pc,3*pc+pa));
    }
    return ans;

  }  


  // BEGIN CUT HERE
public:
  void run_test(int Case) { if ((Case == -1) || (Case == 0)) test_case_0(); if ((Case == -1) || (Case == 1)) test_case_1(); if ((Case == -1) || (Case == 2)) test_case_2(); if ((Case == -1) || (Case == 3)) test_case_3(); if ((Case == -1) || (Case == 4)) test_case_4(); }
private:
  template <typename T> string print_array(const vector<T> &V) { ostringstream os; os << "{ "; for (typename vector<T>::const_iterator iter = V.begin(); iter != V.end(); ++iter) os << '\"' << *iter << "\","; os << " }"; return os.str(); }
  void verify_case(int Case, const double &Expected, const double &Received) { cerr << "Test Case #" << Case << "..."; if (Expected == Received) cerr << "PASSED" << endl; else { cerr << "FAILED" << endl; cerr << "\tExpected: \"" << Expected << '\"' << endl; cerr << "\tReceived: \"" << Received << '\"' << endl; } }
  void test_case_0() { int Arr0[] = {100, 100, 100}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {100, 100, 100}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arr2[] = {100, 100, 100}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); double Arg3 = 3.999999999999999; verify_case(0, Arg3, bestScore(Arg0, Arg1, Arg2)); }
  void test_case_1() { int Arr0[] = {300}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {0}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arr2[] = {0}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); double Arg3 = 3.0; verify_case(1, Arg3, bestScore(Arg0, Arg1, Arg2)); }
  void test_case_2() { int Arr0[] = {300, 0,   0}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {0,   300, 0}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arr2[] = {0,   0,   300}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); double Arg3 = 6.333333333333332; verify_case(2, Arg3, bestScore(Arg0, Arg1, Arg2)); }
  void test_case_3() { int Arr0[] = {100,  0}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {200, 100}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arr2[] = {0,   200}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); double Arg3 = 3.7222222222222223; verify_case(3, Arg3, bestScore(Arg0, Arg1, Arg2)); }
  void test_case_4() { int Arr0[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
                     ,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
                     ,0,0,0,0,0,0,0,0,0}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arr1[] = {150,300,300,300,300,300,300,300,300,300,300,300,300,300
                                                                      ,300,300,300,300,300,300,300,300,300,300,300,300,300,300
                                                                      ,300,300,300,300,300,300,300,300,300,300,300,300,300,300
                                                                      ,300,300,300,300,300,300,300,300}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arr2[] = {150,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
                                                                                                                                 ,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
                                                                                                                                 ,0,0,0,0,0,0,0,0,0}; vector <int> Arg2(Arr2, Arr2 + (sizeof(Arr2) / sizeof(Arr2[0]))); double Arg3 = 149.00000000000003; verify_case(4, Arg3, bestScore(Arg0, Arg1, Arg2)); }

  // END CUT HERE

};  

// BEGIN CUT HERE  
int main()  
{  
  RockPaperScissors ___test;  
  ___test.run_test(-1);  
  system("pause");  
}  
// END CUT HERE  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值