题意:给你一个整数S,有各种类型面值不一的硬币,求刚好凑成S所需的最大数量以及最小数量。
分析:
其本质也是DAG问题,S可以由一个个硬币凑出来,每使用一个硬币i,其状态就转移到了S-i;它的起点是S,终点是0
求最长路的代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxx=10000;
int dp[maxx];
int S,n,V[maxx];
int DP(int i)
{
int &ans=dp[i];
if(ans!=-1)
return ans;
ans=-(1<<30);
for(int j=1;j<=n;j++)
if(i>=V[j])
ans=max(ans,DP(i-V[j])+1);
return ans;
}
int main()
{
cin>>S>>n;
for(int i=1;i<=n;i++)
cin>>V[i];
memset(dp,-1,sizeof(dp));
cout<<DP(S)<<endl;
return 0;
}
求最大和最小数量也可以利用递推,递推更加方便:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int INF=(1<<30);
const int maxn=10000;
int minv[maxn],maxv[maxn];
int V[maxn],S,n;
int main()
{
minv[0]=maxv[0]=0;
cin>>S>>n;
for(int i=1;i<=n;i++)
cin>>V[i];
for(int i=1;i<=S;i++)
{
minv[i]=INF;
maxv[i]=-INF;
}
for(int i=1;i<=S;i++)
for(int j=1;j<=n;j++)
{
if(i>=V[j])
{
minv[i]=min(minv[i],minv[i-V[j]]+1);
maxv[i]=max(maxv[i],maxv[i-V[j]]+1);
}
}
cout<<minv[S]<<" "<<maxv[S]<<endl;
return 0;
}
这个问题和DAG问题差别不大,还是的好好体会DAG啊,感觉很有用啊,继续学习下去,加油!!!!