一场比赛让自己看到了学了这么长时间,竟然还有这么多落下的东西。
区间DP,通过先求小区间的最优解,然后通过小区间的最优解来得到大区间的最优解。
区间DP板子
for(int len = 2; len <= N; len++)//枚举区间的长度,长度是从2开始的,从一开始是貌似没什么意思
for(int st = 0; st < N; st++)//枚举区间的开始 //有的题目甚至还会出错,具体问题具体分析吧
{
int mmin = INF;//注意mmin的位置,mmin在这里求得每个区间长度中的最小值
int en = st + len;//获得区间的结尾
if(en > N) break;
for(int k = st + 1; k < en; k++)
{
int t =dp[st][k] + dp[k][en] + cost[en] - cost[st];
mmin = min(mmin, t);
}
if(mmin != INF)
dp[st][en] = mmin;
}
//这里的cost用的是前缀和数组,注意前缀和数组的处理方法
另外就是区间DP是连续相邻的,一定要与哈夫曼区分开来(wa到吐血的教训)!!
附板子题链接(石子归并)
AC代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <set>
#define INF 0x3f3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 105;
int cost[maxn],dp[maxn][maxn];
int N;
int main()
{
memset(cost, 0, sizeof(cost));
memset(dp, 0, sizeof(dp));
scanf("%d",&N);
for(int i = 1; i <= N; i++)
{
scanf("%d",&cost[i]);
}
cost[0] = 0;
for(int i = 1; i <= N; i++)
{
cost[i] = cost[i-1] + cost[i];
//printf("sum:%d ",cost[i]);
}
for(int len = 2; len <= N; len++)//枚举区间的长度,长度是从2开始的,从一开始是貌似没什么意思
for(int st = 0; st < N; st++)//枚举区间的开始 //有的题目甚至还会出错,具体问题具体分析吧
{
int mmin = INF;//注意mmin的位置,mmin在这里求得每个区间长度中的最小值
int en = st + len;//获得区间的结尾
if(en > N) break;
for(int k = st + 1; k < en; k++)
{
int t =dp[st][k] + dp[k][en] + cost[en] - cost[st];
mmin = min(mmin, t);
}
if(mmin != INF)
dp[st][en] = mmin;
}
//这里的cost用的是前缀和数组,注意前缀和数组的处理方法
printf("%d\n",dp[0][N]);
return 0;
}