POJ3071(確率DP)

                                                             フットボール

 質問の意味:

2つの関わるシングル・エリミネーションのサッカートーナメント考えてみましょうn個  のチームを、1、2、...、2表記のnをトーナメントの各ラウンドでは、トーナメントでまだすべてのチームは、インデックスが増加する順にリストに配置されています。その後、リストの最初のチームは第2チームを果たし、第三のチームは、これらの試合の勝者は、次のラウンドに進むなど、第四のチームを果たし、敗者が除去されます。後に  n個の  ラウンド、一つだけのチームは無敗のまま。このチームが勝者を宣言されています。

行列を考えると  P  = [ p個のIJよう]  のp ijは  そのチームが確率である  私は  、チーム負かす事になります  jは  試合では、トーナメントに勝つ可能性が最も高いとするチームを決定します。

入力:

入力テストファイルは、複数のテストケースが含まれています。各テストケースを含む単一の行で開始され  、N  (1≤  N  ≤7)。次の2つのN  行はそれぞれ2つの含有N  の値を、ここで、  Jの値番目の  I番目のラインは表し  p個のIJを行列  Pは、  その制約を満足させる  のp IJ  - = 1.0  のp JI  すべてのために  私は  ≠  jであり、  P II  のすべてのために= 0.0  Iエンドオブファイルが数-1を含有する1本の線で示されています。この問題の行列の各エントリは、浮動小数点値として与えられることに留意されたいです。あなたがいずれかを使用していることを確認し、精度の問題を回避するために、  double 代わりのデータ型を float

出力:

出力ファイルは、勝つ可能性が最も高いチームの数を示す各テストケースのための単一の行を含める必要があります。浮動小数点の精度の問題を防ぐためには、上位2チームの勝利確率の差が少なくとも0.01になることが保証されます。

サンプル入力

2 
0.0 0.1 0.2 0.3 
0.9 0.0 0.4 0.5 
0.8 0.6 0.0 0.6 
0.7 0.5 0.4 0.0 
-1

サンプル出力

2 

効果の対象:二十から二進行ノックアウト、これだけ最後のチームで最も勝つためにあなたの可能性を問う2つのチームに隣接する2のチームのn乗を与えます。
対象は[i] [j]は、i番目のイニングでJ-Winのチームという確率を表すDP、DPを解決するために、確率論的な思考を使用することができ、その後、次のコードがあります:
//num表示队伍的总数 
for(int i=1;i<=num;i++) 
dp[0][i]=1; // 每只队伍在刚开始比赛的时候(第0局)获胜的概率为1 
        for(int i=1;i<=n;i++)  //表示总共进性n局 
        {
            for(int j=1;j<=num;j++) //表示第i局j获胜 
            {
                for(int k=1;k<=num;k++)//表示第i局k失败 
                {
                  //递推公式 
                }
            }
        }

然后就是递推公式,dp[i][j]+=dp[i-1][j]*dp[i-1][k]*map[j][k].此递推公式很好理解,j如果想在第i局中打败k的

话,其获胜的概率就等于在上一局中j获胜的概率*上一局中k获胜的概率*j打败k的概率,然而只有当一定条件

下j和k才会相遇,假设总共有八只队伍,第一只和第三只队伍只可能在第二局中相遇,第一只和第八只只可能在

第三局中相遇,这个问题可以用if来进行以此判断,判断条件在代码中

#include<iostream>
#include<cmath>
#include<string.h>
#include<algorithm>
using namespace std;
int main()
{
    double map[200][200],dp[10][200];
    int n;
    while(cin>>n)
    {
        memset(dp,0,sizeof(dp));
        if(n==-1) break;
        int num=1<<n;
        for(int i=1;i<=num;i++)
      {
        for(int j=1;j<=num;j++) cin>>map[i][j];
      }
        for(int i=1;i<=num;i++) dp[0][i]=1;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=num;j++)
            {
                for(int k=1;k<=num;k++)
                {
                    if ((((j-1) >> (i-1)) ^ 1) == ((k-1) >> (i-1)))
                        dp[i][j] += dp[i-1][j] * dp[i-1][k] * map[j][k];
                }
            }
        }
      double max=0.0;
      int ans;
      for(int i=1;i<=num;i++)
      {
          if(dp[n][i]>max)
          {
              max=dp[n][i];
              ans=i;
        }
      }
      cout<<ans<<endl; 
    }    
    return 0;
} 

___________________________________________________________________________________________________________________





おすすめ

転載: www.cnblogs.com/tombraider-shadow/p/10959836.html