您的位置:首页 > 其它

poj 1141(区间dp 滚动数组)

2017-04-03 15:41 204 查看
题意:有M个人,我们任选3个人组成一个队伍,可以组成C(M,3)种队伍,给出这些队伍之间的胜率。现在,需要你战胜N个队伍。战胜该队伍,你可选择用战胜的队伍来替换你现有的队伍。现在要求战胜这N个队伍的最大概率。

思路:因为对于战胜的队伍,我们可以选择替换还是不替换,这就像01背包。因为N非常大,我们需要考虑O(N)的递推方程。

如果我们从前向后递推,会存在一个后效性的问题,就是,当前的最优解可能不是全局的最优解。这就暗示了我们需要从后往前递推。

如何从后向前递推呢?因为最后一个被战胜的队伍是确定的,那每个队战胜该队的概率就是确定的。而对于其他的队,我们有两种方式来战胜它,保持原来的队伍不变,用前一个队来替换自己的队伍来战胜它。而到底用哪一个就是取决与其中的最大值。

因为有前后关系,我们要利用滚动数组。

自己的分析:因为前面不知道换不换队伍,如果更改队伍,那么判断条件是用以前上面的作为判定依据,而改了以后,相当于把以前上面的都改了,无法继续为下面做判断。但是下面的所有情况都是确定的,当前是可以根据以前的较大值而确定。

、、、简单说,就是如果从前往后,你不知道换了以后的情况,但是从后往前,你可以知道换了以后是怎么样的,可以做比较。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
double dp[1010][1010];
int AI[10100];
double p[1010][1010];
int main()
{
int n,M;
while(scanf("%d",&M)!=EOF)
{
memset(dp,0,sizeof(dp));
n=M*(M-1)*(M-2)/6;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
scanf("%lf",&p[i][j]);
}
}
int m;
scanf("%d",&m);
for(int i=1;i<=m;i++)
scanf("%d",&AI[i]);
for(int i=0;i<n;i++)
{
dp[m&1][i]=p[i][AI[m]];
}
for(int i=m-1;i>=1;i--)
{
for(int j=0;j<n;j++)
{
dp[i&1][j]=p[j][AI[i]]*max(dp[(i+1)&1][j],dp[(i+1)&1][AI[i]]);
//只拿j队和不断交换的,因为从后往前,所以相当于乘上下面不一样的
}
}
double ans=0;
for(int i=0;i<n;i++)
{
ans=max(ans,dp[1][i]);
}
printf("%.6lf\n",ans );
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: