YbtOJ 「动态规划」第2章 区间DP

例题1.石子合并

断环为链,最小值 f1[i][j]=min(f1[i][j],f1[i][k]+f1[k+1][j]+s[j]-s[i-1])。最大值同理。

code
#include<cstdio>
#include<iostream>
using namespace std;
const int inf=1e9;
int n,a[201],s[201];
int f1[201][201],f2[201][201];
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		a[i+n]=a[i];
	}
	for(int i=1;i<=2*n;i++) s[i]=s[i-1]+a[i];
	for(int i=1;i<=2*n;i++)
		for(int j=1;j<=2*n;j++)
			f1[i][j]=inf,f2[i][j]=0; 
	for(int i=1;i<=2*n;i++) f1[i][i]=0,f2[i][i]=0;
	for(int l=2;l<=n;l++)
	{
		for(int i=1;i<=n*2-l+1;i++)
		{
			int j=i+l-1;
			for(int k=i;k<j;k++)
			{
				f1[i][j]=min(f1[i][j],f1[i][k]+f1[k+1][j]+s[j]-s[i-1]);
				f2[i][j]=max(f2[i][j],f2[i][k]+f2[k+1][j]+s[j]-s[i-1]);
			}
		}
	}
	int maxn=0,minn=inf;
	for(int i=1;i<=n;i++)
	{
		maxn=max(maxn,f2[i][i+n-1]);
		minn=min(minn,f1[i][i+n-1]);
		//cout<<"i="<<i<<";minn="<<minn<<endl;
	}
	cout<<minn<<endl<<maxn<<endl;
	return 0;
}

例题2.木板涂色

处理连续刷一段的情况:当前区间两边颜色相同就把答案减去 1。

code
#include<bits/stdc++.h>
using namespace std;
const int N=205;
char s[N];
int n,f[N][N];
int main()
{
	scanf("%s",s+1);n=strlen(s+1);
	memset(f,0x3f,sizeof(f));
	for(int i=1;i<=n;i++) f[i][i]=1;
	for(int l=2;l<=n;l++)
	{
		for(int i=1;i<=n-l+1;i++)
		{
			int j=i+l-1;
			for(int k=i;k<j;k++)
				f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]);
			if(s[i]==s[j]) f[i][j]--;
		}
	}
	cout<<f[1][n]<<endl;
	return 0;
}
posted @ 2022-08-16 14:16  樱雪喵  阅读(35)  评论(0编辑  收藏  举报