动态规划练习

字面意思:以区间为下标的dp

 

总纲:

https://user.qzone.qq.com/50222268/blog/1503908740?p_skey=nKZcP6pT3RWY56MMKDZuaOyxcgNugQ*rv65G0XZp1jc_

 

题目1:https://www.luogu.org/problemnew/show/P1880#sub

注意:这是个环!!!复制一遍即可

#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

const int maxSize=200,maxValue=0x7fffffff;
int n;
int a[maxSize+5],f1[maxSize+5][maxSize+5],f2[maxSize+5][maxSize+5],sum[maxSize+5][maxSize+5];

void dp()
{
	int i,j,k,min1=maxValue,max1=0;
	
	for (i=1;i<n;i++)	//区间大小 
	{
		for (j=0;i+j<2*n;j++)//起始位置 
		{
			for (k=j;k<i+j;k++)//中间插入位置 
			{
				f1[j][i+j]=min(f1[j][i+j],f1[j][k]+f1[k+1][i+j]+sum[j][i+j]);
				f2[j][i+j]=max(f2[j][i+j],f2[j][k]+f2[k+1][i+j]+sum[j][i+j]);				
			}
		}
	}
	for (i=0;i<=n;i++)
	{
		min1=min(min1,f1[i][i+n-1]);
		max1=max(max1,f2[i][i+n-1]);
	}
	printf("%d\n%d\n",min1,max1);
}

int main()
{
	int i,j,k;
	
	freopen("a.txt","r",stdin);
	scanf("%d",&n);
	for (i=0;i<n;i++)
		scanf("%d",&a[i]);
		
	for (i=0;i<2*n;i++)
		for (j=i;j<=2*n;j++)
		{
			f1[i][j]=maxValue;
			f2[i][j]=0;
		}
	for (i=0;i<2*n;i++)
	{
		f1[i][i]=0;
		f2[i][i]=0;
	}
	
	for (i=0;i<n;i++)
		for (j=0;j<2*n;j++)
			for (k=j;k<=i+j;k++)
			{
				if (k>=n)
					sum[j][i+j]+=a[k-n];
				else
					sum[j][i+j]+=a[k];
			}
	dp();
	
	return 0;
}

 

题目2:https://www.luogu.org/problemnew/show/P1854#sub

一次ac

#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

const int maxSize=100;
int F,v;
int f[maxSize+5][maxSize+5],a[maxSize+5][maxSize+5],f1[maxSize+5][maxSize+5],ans[maxSize+5];

void dp()
{
	int i,j,k,max1,max2;
	
	for (i=2;i<=F;i++)
	{
		for (j=i;j<=v-F+i;j++)
		{
			for (k=i-1;k<j;k++)
			{
				if (f[i][j]<f[i-1][k]+a[i][j])
				{
					f[i][j]=f[i-1][k]+a[i][j];
					f1[i][j]=k;
				}
			}
		}
	}
	max1=0;
	for (i=F;i<=v;i++)
		if (max1<f[F][i])
		{
			max1=f[F][i];
			ans[F]=i;
		}
		
	printf("%d\n",max1);
	for (i=F-1;i>0;i--)
	{
		ans[i]=f1[i+1][ans[i+1]];
	}
	for (i=1;i<=F;i++)
		printf("%d ",ans[i]);
}

int main()
{
	int i,j;
	
	freopen("a.txt","r",stdin);
	scanf("%d%d",&F,&v);
	
	for (i=1;i<=F;i++)
		for (j=1;j<=v;j++)
			scanf("%d",&a[i][j]);
	
	memset(f,0,sizeof(f));
	for (i=1;i<=v-F+1;i++)
		f[1][i]=a[1][i];
	dp();
	
	
	return 0;
}

 

3.题目:https://www.luogu.org/problemnew/show/P1006#sub

注意&&  ||

#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

const int maxSize=50;
int m,n;
int a[maxSize+5][maxSize+5],f[maxSize+5][maxSize+5][maxSize+5][maxSize+5];

int maxium(int i,int j,int k,int l)
{
	return max(max(f[i][j][k][l],f[i-1][j][k-1][l]+a[i][j]+a[k][l]),max(f[i][j-1][k][l-1],max(f[i][j-1][k-1][l],f[i-1][j][k][l-1]))+a[i][j]+a[k][l]);
}

void dp()
{
	int i,j,k,l;
	
	for (i=1;i<=m;i++)
	{
		for (j=1;j<=n;j++)
		{
			for (k=1;k<=m;k++)
			{
				for (l=1;l<=n;l++)
				{
					if (i==k && j==l && (i!=m || j!=n))
						f[i][j][k][l]=-1;
					else
						f[i][j][k][l]=maxium(i,j,k,l);
				}
			}
		}
	}
	printf("%d\n",f[m][n][m][n]);
}

int main()
{
	int i,j;
	
	freopen("a.txt","r",stdin);
	scanf("%d%d",&m,&n);
	
	for (i=1;i<=m;i++)
	{
		for (j=1;j<=n;j++)
			scanf("%d",&a[i][j]);
	}
	dp();
	
	
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值