poj 1141(区间dp 滚动数组)

题意:有M个人,我们任选3个人组成一个队伍,可以组成C(M,3)种队伍,给出这些队伍之间的胜率。现在,需要你战胜N个队伍。战胜该队伍,你可选择用战胜的队伍来替换你现有的队伍。现在要求战胜这N个队伍的最大概率。
思路:因为对于战胜的队伍,我们可以选择替换还是不替换,这就像01背包。因为N非常大,我们需要考虑O(N)的递推方程。
如果我们从前向后递推,会存在一个后效性的问题,就是,当前的最优解可能不是全局的最优解。这就暗示了我们需要从后往前递推。
如何从后向前递推呢?因为最后一个被战胜的队伍是确定的,那每个队战胜该队的概率就是确定的。而对于其他的队,我们有两种方式来战胜它,保持原来的队伍不变,用前一个队来替换自己的队伍来战胜它。而到底用哪一个就是取决与其中的最大值。
因为有前后关系,我们要利用滚动数组。

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

#include 
#include 
#include 
#include 
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;ifor(int j=0;jscanf("%lf",&p[i][j]);      
        }
    }
    int m;
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
        scanf("%d",&AI[i]);
    for(int i=0;i1][i]=p[i][AI[m]];
    }
    for(int i=m-1;i>=1;i--)
    {
        for(int j=0;j1][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;i1][i]);
    }
    printf("%.6lf\n",ans );
}
}

你可能感兴趣的:(dp,区间dp)