ZOJ - 3735
题目大意:
游戏共有m个角色,3个角色组成一个战队,有
个战队,i战队打败j战队的概率为p[i][j].游戏有n轮,每轮对方都会有一个战队与你对战,游戏开始时你可以选择任意一个战队进行游戏,每轮结束后如果你胜出,可以进行下一轮,并且可以把自己使用的战队更换为刚打败的战队,求通关的最大胜率。
题解:
dp[i][j]代表是对战前i个队伍后且当前的队伍是j的最大胜率。
不换的情况
dp[i][j]=dp[i-1][j]*a[j][enemy] dp[i][j]可以由dp[i-1][j]转移过来
换的情况
dp[i][enemy]=dp[i-1][j]*a[j][enemy] 第i-1轮用j队和enemy对打
这里的乘以概率只是为了得到获胜的概率,因为只有获胜才能往下继续,至于获胜之后的两种选择换和不换才产生了循环里的两个语句,一个换,一个不换。
有人可能会觉得,为什么不乘以50%呢,就是换是50%,不换是50%
注意这里是可能换可能不换,至于到底换不换我们是看怎样做最后结果最大,而不是每次一定是50%的几率换,50%的几率不换,所以不能乘以50%,这就相当于是dfs中选还是不选,两种情况。
最后diss一下题意,本场比赛真是读题到自闭,好久才搞明白,体验很不爽
#include<bits/stdc++.h>
#include<cstring>
using namespace std;
#define ll long long
double a[150][150];
double dp[10010][150];
int main()
{
//freopen("input.txt","r",stdin);
int m;
while(cin>>m)
{
int len=m*(m-1)*(m-2)/6;
for(int i=1; i<=len; ++i)
for(int j=1; j<=len; ++j)
cin>>a[i][j];
//dp[i][j]代表是对战前i个队伍后且当前的队伍是j的最大胜率。。
int n;
cin>>n;
memset(dp,0,sizeof(dp));
for(int i=1; i<=len; ++i)
dp[0][i]=1;
int enemy;
for(int i=1; i<=n; ++i)
{
cin>>enemy;
++enemy;
for(int j=1; j<=len; ++j)
{
dp[i][j]=max(dp[i][j],dp[i-1][j]*a[j][enemy]);//不换
dp[i][enemy]=max(dp[i][enemy],dp[i-1][j]*a[j][enemy]);//换
}
}
double ans=0;
for(int i=1; i<=len; ++i)
ans=max(ans,dp[n][i]);
cout<<fixed<<setprecision(8)<<ans<<endl;
}
return 0;
}