游戏人生
区间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];
}
}
把循环改一下这样不用初始化了
巧妙之处自己体会