动态规划
来源:互联网 发布:沙盘软件多开器 编辑:程序博客网 时间:2024/06/08 07:51
动态规划的介绍
动态规划一般也只能应用于有最优子结构的问题。最优子结构的意思是局部最优解能决定全局最优解(对有些问题这个要求并不能完全满足,故有时需要引入一定的近似)。简单地说,问题能够分解成子问题来解决。
动态规划算法的4个步骤:
1.描述最优解的结构
2.递归定义最优解的值
3.按自底向上的方式计算最优解的值 //此3步构成动态规划解的基础。
4.由计算出的结果构造一个最优解。 //此步如果只要求计算最优解的值时,可省略。
一,缓存与动态规划
例题一:有一段楼梯有10级台阶,规定每一步只能跨一级或两级,要登上第10级台阶有几种不同的走法?
分析:由题目得出f(n) = f(n-1) + f(n-2)
解法一:void walk_one(int n) //此题使用递归算法
{
if(n>10)
{
return;
}
if(n==10)
{
Count++;
return;
}
walk_one(n+1);
walk_one(n+2);
}
解法二:int walk_two(int n) //在递归算法的基础上添加了动态规划的思想,对于需要重复进行的运算进行记忆
{
if(n<0)
{
return 0;
}
if(n==0)
{
return 1;
}
return walk_two(n-1)+walk_two(n-2);
}
解法三:int walk_three(int n) //同上
{
if(n>0&&n<=2) //f(1) = 1; f(2) = 2;
{
return n;
}
return walk_two(n-1)+walk_two(n-2);
}
解法四:int walk_four() //舍去递归,根据总结的规律,直接使用循环进行动态规划
{
int num[10];
int i=0;
num[1] = 2,num[0] = 1;
for(i=2;i<10;i++)
{
num[i] = num[i-1]+num[i-2];
}
return num[9];
}
例题二:背包问题
/*
背包问题:
有n个重量和价值分别为weight,value的物品;背包最大负重为W,求能用背包装下的物品的最大价值?
输入:n =4 W=5
weight=2, 1, 3, 2
value =3, 2, 4, 2
输出=7*/
解法一:
//!!!!!!!!!!!!!!!!!!里面含有重复计算,耗费大量时间!!!!!!!!!!!!!!!!!!!!!//
#include <stdio.h>
#define MAX(a,b) a>b?a:b
#define M 10
int v[M]={0},w[M]={0};
int num=0;
int main(void)
{
int find(int,int);
int i=0;
int big=0;
scanf("%d %d",&num,&big);
for(i=0;i<num;i++)
{
scanf("%d %d",w+i,v+i);
}
printf("%d\n",find(0,big));
return 0;
}
int find(int i,int have)
{
int res;
if(have<=0||i>=num)
{
return 0;
}
if(have<w[i])
{
res = find(i+1,have);
}
else
{
res = MAX(find(i+1,have),find(i+1,have-w[i])+v[i]);
}
return res;
}
解法二:
//递归转换成循环
int find_2(int bag)
{
int i=0,j=0;
int dp[M][M]={0}; //背包考虑放置i物品时,剩余背包容量为j;如果j的值小于此时i的体积,直接跳到下一个物品。
for(i=num-1;i>=0;--i) //如果j>i的体积,则考虑是放置i产生的价值大还是不放置价值大。
{
for(j=0;j<=bag;++j)
{
if(j<w[i])
dp[i][j] = dp[i+1][j];
else
dp[i][j] = MAX(dp[i+1][j],dp[i+1][j-w[i]]+v[i]);
}
}
return dp[0][bag];
}
动态规划一般也只能应用于有最优子结构的问题。最优子结构的意思是局部最优解能决定全局最优解(对有些问题这个要求并不能完全满足,故有时需要引入一定的近似)。简单地说,问题能够分解成子问题来解决。
动态规划算法的4个步骤:
1.描述最优解的结构
2.递归定义最优解的值
3.按自底向上的方式计算最优解的值 //此3步构成动态规划解的基础。
4.由计算出的结果构造一个最优解。 //此步如果只要求计算最优解的值时,可省略。
!!!!!将递归变为循环,这就是动态规划!!!!!!!!!!
一,缓存与动态规划
例题一:有一段楼梯有10级台阶,规定每一步只能跨一级或两级,要登上第10级台阶有几种不同的走法?
分析:由题目得出f(n) = f(n-1) + f(n-2)
解法一:void walk_one(int n) //此题使用递归算法
{
if(n>10)
{
return;
}
if(n==10)
{
Count++;
return;
}
walk_one(n+1);
walk_one(n+2);
}
解法二:int walk_two(int n) //在递归算法的基础上添加了动态规划的思想,对于需要重复进行的运算进行记忆
{
if(n<0)
{
return 0;
}
if(n==0)
{
return 1;
}
return walk_two(n-1)+walk_two(n-2);
}
解法三:int walk_three(int n) //同上
{
if(n>0&&n<=2) //f(1) = 1; f(2) = 2;
{
return n;
}
return walk_two(n-1)+walk_two(n-2);
}
解法四:int walk_four() //舍去递归,根据总结的规律,直接使用循环进行动态规划
{
int num[10];
int i=0;
num[1] = 2,num[0] = 1;
for(i=2;i<10;i++)
{
num[i] = num[i-1]+num[i-2];
}
return num[9];
}
例题二:背包问题
/*
背包问题:
有n个重量和价值分别为weight,value的物品;背包最大负重为W,求能用背包装下的物品的最大价值?
输入:n =4 W=5
weight=2, 1, 3, 2
value =3, 2, 4, 2
输出=7*/
解法一:
//!!!!!!!!!!!!!!!!!!里面含有重复计算,耗费大量时间!!!!!!!!!!!!!!!!!!!!!//
#include <stdio.h>
#define MAX(a,b) a>b?a:b
#define M 10
int v[M]={0},w[M]={0};
int num=0;
int main(void)
{
int find(int,int);
int i=0;
int big=0;
scanf("%d %d",&num,&big);
for(i=0;i<num;i++)
{
scanf("%d %d",w+i,v+i);
}
printf("%d\n",find(0,big));
return 0;
}
int find(int i,int have)
{
int res;
if(have<=0||i>=num)
{
return 0;
}
if(have<w[i])
{
res = find(i+1,have);
}
else
{
res = MAX(find(i+1,have),find(i+1,have-w[i])+v[i]);
}
return res;
}
解法二:
//递归转换成循环
int find_2(int bag)
{
int i=0,j=0;
int dp[M][M]={0}; //背包考虑放置i物品时,剩余背包容量为j;如果j的值小于此时i的体积,直接跳到下一个物品。
for(i=num-1;i>=0;--i) //如果j>i的体积,则考虑是放置i产生的价值大还是不放置价值大。
{
for(j=0;j<=bag;++j)
{
if(j<w[i])
dp[i][j] = dp[i+1][j];
else
dp[i][j] = MAX(dp[i+1][j],dp[i+1][j-w[i]]+v[i]);
}
}
return dp[0][bag];
}
阅读全文
0 0