动态规划DP
贪心算法如下
#include <stdio.h>
#define N 3
int coin[]={1,2,5};
int main(){
int i,money;
int ans[N]={0};
scanf("%d",&money);
for(i=N-1;i>=0;i--) {
ans[i]=money/coin[i];
money=money-ans[i]*coin[i];
}
for(i=N-1;i>=0;i--){
printf("%d:%d",coin[i],ans[i]);
printf("\n");
}
}
用DP解决
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define N 5//纸币的种类
#define n 65535//最大数
#define max 100//最大输入金额
int ans[N]={0};
int coin[]={1,5,10,20,100};
int min(int a,int b)
{
return a>b?b:a;
}
void solve()
{
for(int i=0;i<max;i++)
ans[i]=n;//初始值为无穷大
ans[0]=0;
for(int j=0;j<N;j++)
{
for(int k=coin[j];k<max;k++)
{
ans[k]=min(ans[k],ans[k-coin[j]]+1);//状态转移
}
}
}
int main(){
int money;
scanf("%d",&money);
solve();
if(money==n)
printf("no answer");
else
printf("%d",ans[money]);
}
- DP问题的特征
DP的特征就是用前面子问题的结果,推到后续子问题的解
重叠子问题,最优子结构
- DP的两种编程方法
- DP的设计和实现
- 经典问题
0/1背包问题 选硬币问题
#include<stdio.h>
struct node {
int w,value;
int flag;
}a[100];
int dp[100][100]={0};
int c[100]={0};
void dpdist(int p,int q)
{
int i,j;
for(i=1;i<=p;i++)
{
for(j=1;j<=q;j++)
{
if(a[i].w>j)
dp[i][j]=dp[i-1][j];
else if(dp[i-1][j]>dp[i-1][j-a[i].w])
dp[i][j]=dp[i-1][j];
else
dp[i][j]=dp[i-1][j-a[i].w]+a[i].value;
}
}
printf("最大价值为%d\n",dp[p][q]);
}
void trans(int p,int q)
{
int i=p;
while(p!=0)
{
if(dp[p][q]>dp[p-1][q])
{
c[p]=1;
q-=a[p].w;
}
p=p-1;
}
for(i;i>=1;i--)
{
printf("第%d个物品 是否存放?%d",i,c[i]);
printf("\n");
}
}
int main()
{
int i,p,q;
scanf("%d %d",&p,&q);
for(i=1;i<=p;i++)
{
scanf("%d %d",&a[i].w,&a[i].value);
a[i].flag=i;
}
dpdist(p,q);
trans(p,q);
return 0;
}