动态规划经典问题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
动态规划经典问题
1、三角数塔问题
设有一个三角形的数塔,顶点为根结点,每个结点有一个整数值。从顶点出发,可以向左走
或向右走,如图所示:
要求从根结点开始,请找出一条路径,使路径之和最大,只要输出路径的和。
【代码】
//
// 例题1 三角数字塔问题//
//
#include
#include
#define MAXN 101
intn,d[MAXN][MAXN];
int a[MAXN][MAXN];
voidfnRecursive(int,int);
//递推方法函数声明
intfnMemorySearch(int,int);
//记忆化搜索函数声明
int main()
{
inti,j;
printf("输入三角形的行数n(n=1-100):\n");
scanf("%d",&n);
printf("按行输入数字三角形上的数(1-100):\n");
for(i=1; i<=n; i++)
for(j=1; j<=i; j++)
scanf("%d",&a[i][j]);
for(i=1; i<=n; i++)
for(j=1; j<=i; j++)
d[i][j]=-1;//初始化指标数组
printf("递推方法:1\n记忆化搜索方法:2\n");
int select;
scanf("%d",&select);
if(select==1)
{
fnRecursive(i,j);//调用递推方法
printf("\n%d\n",d[1][1]);
}
if(select==2)
{
printf("\n%d\n",fnMemorySearch(1,1));//调用记忆化搜索方法}
else
printf("输入错误!");
return 0;
}
voidfnRecursive(inti,int j)
//递推方法实现过程
{
for(j=1; j<=n; j++)
d[n][j]=a[n][j];
for(i=n-1; i>=1; i--)
for(j=1; j<=i; j++)
d[i][j]=a[i][j]+(d[i+1][j]>d[i+1][j+1]?d[i+1][j]:d[i+1][j+1]); }
intfnMemorySearch(inti,int j)
//记忆化搜索实现过程
{
if(d[i][j]>=0) return d[i][j];
if(i==n) return(d[i][j]=a[i][j]);
if(fnMemorySearch(i+1,j)>fnMemorySearch(i+1,j+1))
return(d[i][j]=(a[i][j]+fnMemorySearch(i+1,j)));
else
return(d[i][j]=(a[i][j]+fnMemorySearch(i+1,j+1)));
}
2、硬币问题
问题描述:有n种硬币,面值分别为V1,V2,…,Vn, 每种有无限多。给定非负整数S,可以选用多少硬币,使得面值之和恰好为S,输出硬币数目的最小值和最大值。
(1<=n<=100,0<=S<=10000,1<=Vi<=S)
【代码】
//
// 例题1 硬币问题//
//
#include
#include
#define INF 100000000
#define MAXNUM 10000
#define MONEYKIND 100
intn,S;
int V[MONEYKIND];
int min[MAXNUM],max[MAXNUM];
voiddp(int*,int*);
//递推方法函数声明
voidprint_ans(int*,int);
//输出函数声明
int main()
{
inti;
printf("输入硬币的种数n(1-100):\n");
scanf("%d",&n);
printf("输入要组合的钱数S(0-10000):\n");
scanf("%d",&S);
printf("输入硬币种类:\n");
for(i=1; i<=n; i++)
{
scanf("%d",&V[i]);
}
dp(min,max);
printf("最小组合方案:\n");
print_ans(min,S);
printf("\n");
printf("最大组合方案:\n");
print_ans(max,S);
return 0;
}
voiddp(int *min,int *max)
//递推过程实现
{
inti,j;
min[0] = max[0] = 0;
for(i=1; i<=S; i++)//初始化数组
{
min[i]=INF;
max[i]=-INF;
}
for(i=1; i<=S; i++)
for(j=1; j<=n; j++)
if(i>=V[j])
{
if(min[i-V[j]]+1 min[i]=min[i-V[j]]+1;//最小组合过程 //printf("%d\n",min[i]); } if(max[i-V[j]]+1>max[i]) max[i]=max[i-V[j]]+1;//最大组合过程 } } voidprint_ans(int *d,int S) //输出函数实现 { inti; for(i=1; i<=n; i++) if(S>=V[i]&&d[S]==d[S-V[i]]+1) { printf("%d-",V[i]); print_ans(d,S-V[i]); break; } } 3、矩形嵌套问题 问题描述:有n个矩形,每个矩形可以用两个整数a,b描述,表示它的长和宽。矩形X(a,b)可以嵌套在矩形Y(c,d)中,当且仅当a 【代码】 //