【动态规划】 小练习

背包问题

/**
***   时间:2018年11月22日
***   问题:有n项作业,每项作业都有各自的完成时间以及收益,求在D时间内做作业获得的最大收益
***   方法:动态规划,递归
**/

#include<stdio.h>
struct task
{
	int time,value;
};

int opt(task p[],int n,int d)
{    
	if(n==0)
		return 0;
	if(p[n].time>d)
		return opt(p,n-1,d);
	else
	{   int A = opt(p,n-1,d-p[n].time) + p[n].value;
		int B = opt(p,n-1,d);
		return A>B?A:B;
	}

}

void main()
{   
	task p[9]={ 0,0,
			  3,5,
			  2,3,
			  4,6,
			  2,2,
			  5,4,
			  1,7,
			  2,9,
			  3,2
	}; 
	int D=13;
	printf("%d\n",opt(p,9-1,D));
}

/*void main()
{   
	task p[7]={ 0,0,
			  2,6,
			  2,3,
			  6,5,
			  5,4,
			  5,4,
			  4,6
	}; 
	int D=10;
	printf("%d\n",opt(p,7-1,10));
}*/

任务安排

/**
***  时间:2018年11月21日
***  问题:任务安排问题。一共有8种任务,每种任务有各自的开始时间和结束时间以及价值,一个时间段只能做一个任务,
***        问11个小时内如何做任务所获得的价值最大。
***  方法:动态规划 
**/
#include<stdio.h>
struct task
{
   int start,end,value;
};
void list(task a[])
{   
	int p[9]={0};
    int i,j;
	for(i=2;i<9;i++)
		for(j=i-1;j>0;j--)
			if(a[i].start==a[j].end)
				p[i]=j;

	int opt[9]={0};
    for(i=1;i<9;i++)
		opt[i]=(a[i].value+opt[p[i]])>opt[i-1]?(a[i].value+opt[p[i]]):opt[i-1];
	for(i=0;i<9;i++)
    printf(" %d",opt[i]);
}
void main()
{    task arr[9]={0,0,0,
			 1,4,5,
			 3,5,1,
			 0,6,8,
			 4,7,4,
			 3,8,6,
			 5,9,3,
			 6,10,2,
			 8,11,4};
	list(arr);
}

选数相加1

/**
***   时间:2018年11月21日
***   问题:从一组数据中挑选若干数字出来相加的最大值是多少,不能选相邻的数;比如说4 1 2 9 1,选了4就不能选4旁边的1
***   方法:动态规划
**/

#include<stdio.h>

void add(int p[])
{
	int i;
	int opt[8]={0};
	opt[1]=p[1];
	for(i=2;i<8;i++)
		opt[i]=(opt[i-2]+p[i])>p[i-1]?(opt[i-2]+p[i]):p[i-1];
	for(i=0;i<8;i++)
	printf("%d ",opt[i]);
}

void main()
{
	int p[8]={0,1,2,4,1,7,8,3};
	add(p);
}

选数相加2

/**
***   时间:2018年11月21日
***   问题:在一组数据中挑选若干个出来是否能组成一个特定的数,比如说在数组 2 5 4 20 中有能组成7
***   方法动态规划
**/
#include<stdio.h>

bool add(int a[],int n,int s)
{
	if(s==0)
		return true;
	if(n==0)
		return a[0]==s;
	if(a[n]>s)
		return add(a,n-1,s);
	bool A = add(a,n-1,s-a[n]);
	bool B = add(a,n-1,s); 
	return A||B;
}

void main()
{
	int a[6]={3,34,4,12,5,2};
	int s=10;
	printf("%d\n",add(a,6-1,s));
}

最大增长子序列

/**
***   时间:2018年11月23日
***   问题:求最大增长子序列。
           设A=<x1,x2,…xi…,xn >是一个由n个不等的整数构成的序列,
		   求A的一个最长单调递增子序列。A的一个单调递增子序列是使得i1<i2<……<ik,
		   且子序列的长度指的是所含有的整数个数,即k。例如A=<1,5,3,8,10,6,4,9>,
		   它的长度为4的递增子序列是<1,5,8,10>或<1,5,8,9>或<1,3,8,10>或<1,3,6,9>或<1,3,4,9>或……。
***   方法:动态规划
***   思路:①如果当前项大于前面的第j项的数值,那么,当前项的最大增长子序列= 第j项的最大增长子序列 + 1,
            但是有一个问题,如果当前项的前面的第k项(k不等于j)也小于当前项的值,该怎么处理
			所以要求比较第j项和第k项的最大增长子序列的长度谁比较大(最优解)
            所以j项的最大增长子序列的长度必须要是当前项前面项中的最大的!
**/

#include<stdio.h>
#include<string.h>
void main()
{
    int p[9]={4,5,1,3,6,7,2,9,8};
	int i,j,point=-1;
	int a[9];
	/**  找出每项的最大增长子序列的长度  **/
	bool flag=false;
	int opt[9]={0};
	for(i=1;i<9;i++)       //从第2项开始,因为第1项没有前一项,
	{	
		for(j=0;j<i;j++)
			if(p[j]<p[i])        
			{
				if(opt[i]>opt[j])         
					opt[i]=opt[i];        
				else 
					opt[i]=opt[j];     //前项的最大增长子序列= 第j项的最大增长子序列
			    	flag = true;       //选中了第j项
			} 
	    if(flag == true)
			opt[i]+=1;                 //当前项的最大增长子序列= 第j项的最大增长子序列 + 1
		flag = false;
	}
    /**  找出所有项中最大增长子序列的长度的最大值  **/
	int max=opt[0],n;
	for(i=1;i<9;i++)
        	if(max<opt[i])
			{
				max=opt[i];
			    n=i;
			}
	/**  输出子序列(从后开始输出,所以需要一个数组保存以正序输出)  **/
	j=0;                      
	max=opt[n];
	for(i=n;i>=0;i--)
	{	
		if(opt[i]==max)
		{	a[j]=p[i];
		    j++;
			max--;
		}
        if(max==-1)
		{
            for(i=j-1;i>=0;i--)
				printf("%d ",a[i]);
			return ;
		}
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值