#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int v[101],s,n,mini[10001],maxn[10001],visi[10001];
int MAX(int a,int b)
{
return a>b?a:b;
}
int MINI(int a,int b)
{
return a<b?a:b;
}
int dp_mini(int ss)
{
if(visi[ss]) return mini[ss];
visi[ss] = 1;
mini[ss] = (1<<30);
for(int i=1;i<=n;++i)
if(ss>=v[i]) mini[ss] = MINI(mini[ss],dp_mini(ss-v[i])+1);
return mini[ss];
}
int dp_max(int ss)
{
if(visi[ss]) return maxn[ss];
visi[ss] = 1;
maxn[ss] = -(1<<30);
for(int i=1;i<=n;++i)
if(ss >= v[i]) maxn[ss] = MAX(maxn[ss],dp_max(ss-v[i])+1);
return maxn[ss];
}
int solve_mini()
{
for(int i=1;i<=s;++i)
mini[i] = (1<<30);
mini[0] = 0;
for(int i=1;i<=s;++i)
for(int j=1;j<=n;++j)
if(i >= v[j]) mini[i] = MINI(mini[i],mini[i-v[j]]+1);
return mini[s];
}
int solve_max()
{
for(int i=1;i<=s;++i)
maxn[i] = -(1<<30);
maxn[0] = 0;
for(int i=1;i<=s;++i)
for(int j=1;j<=n;++j)
if(i>=v[j]) maxn[i] = MAX(maxn[i],maxn[i-v[j]]+1);
return maxn[s];
}
int main()
{
scanf("%d %d",&n,&s);
for(int i=1;i<=n;++i)
scanf("%d",&v[i]);
memset(visi,0,sizeof(visi));
visi[0]=1;//這一步初始化很關鍵,原書並未強調
int mini1 = dp_mini(s);
memset(visi,0,sizeof(visi));
visi[0]=1;
int max1 = dp_max(s);
int mini2 = solve_mini();
int max2 = solve_max();
printf("%d %d\n%d %d\n",mini1,max1,mini2,max2);
return 0;
}
入門經典--硬幣問題dp遞歸加遞推
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.