动态规划题目

@TOC动态规划题目

一、经典背包问题

*
背包问题
给出n个物品的体积A[i][0]和其价值A[i][1],将他们装入一个大小为k的背包,最多能装入的总价值有多大?

*/

#include<stdio.h>
//N个背包
#define N  4
int max(int a, int b)
{
	return a>b?a:b;
}
int main()
{	
	//i表示背包的编号 a[i][0]  表示背包的大小   a[i][1]表示背包的价值   a[0][0]表示背包的大小和 容量均为0
	//大小 价值
	int a[N+1][2]={ {0,  0},
					{2,  3},
					{3,  4},
					{4,  5},
					{5,  6}};
	int k;
	printf("请输入总容量的大小:");
	scanf("%d",&k);
	int sub[N+1][k+1];
	//sub[i][j]  j表示剩余容量 i表示      有几个背包可供选择
	//a[i][j]容量为j的容器能装的价值的最大值
	//0个背包可供选择的情况下 无论容量多大 均没得装 即最大价值均为0
	for(int i=0;i<=k;i++)
	{
		sub[0][i]=0;
	}
	//在容量为0的情况下 无论多少个背包可共选择   !均装不下 即最大价值为0
	for(int i=0;i<=N;i++)
	{
		sub[i][0]=0;
	} 
	for(int i=1;i<=N;i++)
	{
		for(int j=1;j<=k;j++)
		{
			if(j>=a[i][0])
			{
				int m=a[i][1]+sub[i-1][j-a[i][0]];	//选择当前背包    当前背包的价值 加上  (剩下的背包选择中(i-1) 容量为 总容量减去当前背包的大小)的最高价选择
				int n=sub[i-1][j];				  	//不选择当前背包 那就是容量为 j   背包选择为 i-1的最高选择
				sub[i][j]=max(m,n);  
			}
			else
			{
				//当前容量装不下这个背包  那么有i个背包的选择情况下,他的最大值也只能是有i-1个背包的最大值
				sub[i][j]=sub[i-1][j];
			}
		}
	}
	for(int i=0;i<=N;i++)
	{
		for(int j=0;j<=k;j++)
		{
			printf("%d ",sub[i][j]);
		}
		printf("\n");
	}

	
}

二、不能连续的子序列最大和

//动态规划里面的
#include<stdio.h>
#define N 7
int  max(int a,int b)
{
	return a>b?a:b ;
}
//不能连续的子序列最大和
int main()
{
	int array[N]={1,2,4,1,7,8,3};
	int opt[N];
	opt[0]=array[0];
	opt[1]=max(array[0],array[1]);
	int prev[N]={0};
	for(int i=N-1;i>=2;i--)//如果选了6  那么就只能选4
	{
		prev[i]=i-2;
	}
	for(int i=2;i<N;i++)
	{
		opt[i]=max(opt[prev[i]]+array[i],opt[i-1]);//选或不选两种情况  
	}
	printf("%d\n",opt[N-1]);
}

三、最长上升子序列

/*
		5.最长上升子序列的长度 
		如:1 4 -3 -9 5 9 0
		如:1,5,2,3,4,6,-5,-9,10,11
		子序列 不要求连续,前后关系要和原序列一致 
*/

#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#define N 10
int max(int a,int b)
{
	return a>b?a:b;
}
int main()
{
	//srand((int)time(0));
	int a[N];
	for(int i=0;i<N;i++)
	{
		a[i]=rand()%10;
	}
	for(int i=0;i<N;i++)
	{
		printf("%3d ",a[i]);
	}
	printf("\n");
	//动态规划
	int Lmax=1;
	int d[N];				//记录当前元素的子序列长度
	for(int i=0;i<N;i++)
	{	
		d[i]=1;				//假设当前元素的上升子序列只有自己  即长度为1;
		for(int j=i-1;j>=0;j--)
		{
			if(a[i]>a[j])
			{
				//选自己的
				d[i]=max(d[i],d[j]+1);//我的最优解等于我前面的比我小的元素的最优解+1
			}
		}
		//和不选自己 Lmax
		Lmax=max(Lmax,d[i]);
		printf("%3d ",Lmax);
	}
	printf("最长上升子序列长度为:%d\n",Lmax);
	
}

四、三角形最短路径

#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#define N 4
int min(int a,int b)
{
	return a>b?b:a;
}
int min_3(int a,int b,int c)
{
	int t=c<(a<b?a:b)?c:(a<b?a:b);
	return t;
}
int main(int argc,char* argv[])
{
	int a[N][N],dp[N][N];
	for(int i = 0;i<N;i++)
	{
		for(int j = 0;j<N;j++)
		{
			a[i][j]=-1;
		}

	}
	
	srand((int)time(0));
//随机数种子
	int  k=2;
	for(int i = 0;i<N;i++)
	{
		for(int j = 0;j<=i;j++)
		{
			a[i][j]=rand()%10+1;   //随机赋值			
		}
	}	
	for(int i = 0;i<N;i++)
	{
		for(int j = 0;j<=i;j++)
		{
			printf("%2d ",a[i][j]);
		}
		printf("\n");
	}
	/******************************/
	dp[0][0]=a[0][0];
	//	printf("%d\n",dp[0][0]);
	for(int i = 1;i<N;i++)
	{
		for(int j = 0;j<=i;j++)
		{	
			if(j==0)//如果左边溢出 
			{	
				if(a[i-1][j+1]==-1)//右上边碰到墙壁只能取到上方
				{
					dp[i][j]=a[i][j]+dp[i-1][j];
				}
				else//右上没有碰到能取上方和右上方
				{
					dp[i][j]=min(dp[i-1][j],dp[i-1][j+1])+a[i][j];
				}				
			}
			else //左边不会溢出
			{
				if(a[i-1][j]==-1)//如果上边碰到只能取左上
				{dp[i][j]=a[i][j]+dp[i-1][j-1];
					
				}
				else if(a[i-1][j+1]==-1)//右上边碰到  只能取到上方和上左
				{
					dp[i][j]=min(dp[i-1][j],dp[i-1][j-1])+a[i][j];
				}
				else			//右边没有碰到能取到上面三个位置
				{
					dp[i][j]=min_3(dp[i-1][j-1],dp[i-1][j],dp[i-1][j+1])+a[i][j];
				}
			}
			//printf("%d ",dp[i][j]);
		}
		//printf("\n");
	}
	int n_min;
	n_min=dp[N-1][0];
	for(int i=0;i<N;i++)
	{
		if(n_min >= dp[N-1][i])
		{
			n_min = dp[N-1][i];
		}
		//printf("%d  ",dp[N-1][i]);
	}
	printf("%d \n",n_min);
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值