NYOJ-1111游戏人生

来源:互联网 发布:电表数据丢失 编辑:程序博客网 时间:2024/06/15 19:02

                                                        游戏人生

区间DP问题
和石子合并又很像
但是题目中有一点没有说明白,导致我卡了很久
比如   1   2    3三只野怪,如果把2野怪杀死,那么1和3就变为相邻了
其他的就比较好想了
状态转移方程的含义:
找一个中间点k,先把从i到k-1的都打死,然后打死k+1到j的
最后打死k
注意,打死k的时候,k的边上是i-1和j+1,所以后面要加一行代码

#include<bits/stdc++.h>using namespace std;int min3(int a,int b,int c){    return min(a,min(b,c));}const int inf=0x3f3f3f3f;const int maxn=205;int m[maxn],f[maxn];int dp[maxn][maxn];int step=0;int main(){    int T;    scanf("%d",&T);    while(T--)    {        int n;        scanf("%d",&n);        memset(dp,0,sizeof(dp));        memset(m,0,sizeof(m));        memset(f,0,sizeof(f));        for(int i=1;i<=n;i++)        {            scanf("%d",&m[i]);        }        for(int i=1;i<=n;i++)        {            scanf("%d",&f[i]);        }        for(int i=1;i<=n;i++)            dp[i][i]=m[i]+f[i-1]+f[i+1];        for(int l=1;l<=n;l++)        {            for(int i=1;i<=n-l;i++)            {                int j=i+l;                dp[i][j]=inf;                for(int k=i;k<=j;k++)                {                    dp[i][j]=min(dp[i][j],dp[i][k-1]+m[k]+dp[k+1][j]);                }                dp[i][j]+=f[i-1]+f[j+1];            }        }        printf("Case #%d: %d\n",++step,dp[1][n]);    }}


这种方法还要初始化一下,比较一般
for(l = 1; l <= n; ++l)          {              for(i = 1; i <= n - l + 1; ++i)              {                  j = i + l - 1;                  dp[i][j] = inf;                  for(int k=i; k<=j; k++)                  {                      dp[i][j]=min(dp[i][j],dp[i][k-1]+m[k]+dp[k+1][j]);                  }                  dp[i][j]+=f[i-1]+f[j+1];              }          }  

把循环改一下这样不用初始化了
巧妙之处自己体会