背包问题
/**
*** 时间: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 ;
}
}
}