DAG model-coins
There are n kinds of coins with denominations of V1, V2,..., Vn, and each has an infinite number. Given a non-negative integer S, how many coins can be used so that the sum of face value is exactly S? Output the minimum and maximum number of coins. 1<=n<=100,0<=S<=10000,1<=Vi<=S.
Idea:
The essence of this question is still the path problem of DAG. Each face value is regarded as a point, and the states maxv(x) and minv(x) are set to represent the longest and shortest paths from the current node to the 0 node, respectively. Find the state transition equation, the initial state is S, and select the optimal solution.
It should be noted that memorized search can reduce a lot of time, but the path in the result of this question can be 0, so all are marked with -1 to distinguish, if it is greater than or equal to 0, it means that the calculation has been performed, and the value is directly returned, otherwise it is marked as 0 , And then perform search calculations.
But this will cause errors. There may be no solution to this question, that is, the point cannot be found at the end, and S is not collected, then it will mistakenly think that it was found. Therefore, the calculated values should be distinguished by other special values, that is, the minimum value and the maximum value. The initial state is all marked with -1, and only the end point is marked with 0.
code show as below:
#include <iostream>
#include <algorithm>
#include <string.h>
#define maxn 105
#define maxvn 10005
using namespace std;
int n,s;
int v[maxn],maxv[maxvn],minv[maxvn];
int dpmax(int s)
{
int i;
int& ans=maxv[s];
if(ans!=-1)
return ans;
ans=-(1<<30);
for(i=1;i<=n;i++)
{
if(s>=v[i])
{
ans=max(ans,dpmax(s-v[i])+1);
}
}
return ans;
}
int dpmin(int s)
{
int i;
int& ans=minv[s];
if(ans!=-1)
return ans;
ans=(1<<30);
for(i=1;i<=n;i++)
{
if(s>=v[i])
{
ans=min(ans,dpmin(s-v[i])+1);
}
}
return ans;
}
int print_max(int s)
{
int i;
for(i=1;i<=n;i++)
{
if(s>=v[i]&&maxv[s]==maxv[s-v[i]]+1)
{
cout<<v[i]<<" ";
print_max(s-v[i]);
break;
}
}
}
int print_min(int s)
{
int i;
for(i=1;i<=n;i++)
{
if(s>=v[i]&&minv[s]==minv[s-v[i]]+1)
{
cout<<v[i]<<" ";
print_min(s-v[i]);
break;
}
}
}
int main()
{
int i;
cin>>n>>s;
for(i=1;i<=n;i++)
{
cin>>v[i];
}
memset(maxv,-1,sizeof(maxv));
maxv[0]=0;
memset(minv,-1,sizeof(minv));
minv[0]=0;
cout<<"min="<<dpmin(s)<<endl;
cout<<"The Path Of Min:"<<endl;
print_min(s);
cout<<endl;
cout<<"max="<<dpmax(s)<<endl;
cout<<"The Path Of Max:"<<endl;
print_max(s);
cout<<endl;
return 0;
}