动态规划的核心是状态和状态转移方程**
- DAG上的动态规划一定要结合图来思考,要心中有图,或者在纸上画图,谨记!这样可以真正理解!求解状态转移方程的过程其实就是在填写一个表格!把表填好了,所有状态就填好了
d(i)定义为以i开始到0结束的最长/短路
/*
最少硬币问题
Sample Input#
3
23
1 2 5
Sample Output#
6
1 2 3 3 3 3
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
#define INF 1000000000
const int maxn=105;
int n;
int S;
int V[maxn];
int d[maxn];
void input()
{
cin>>n>>S;
for(int i = 1; i <= n; i++) cin >> V[i];
}
//这里要注意表示dp的状态值: 因为最小值可能是0, 所以不能用0代表没算过,而是用-1代表没算过。INF代表不可达。
int dp(int S)
{
int &ans=d[S];
if(ans!=-1) return ans;
ans=INF;//表示不可达
for(int i=1;i<=n;i++)
if(S>=V[i])
{
ans=min(dp(S-V[i])+1, ans);
}
return ans;
}
void print_ans(int* d, int S){
for(int i=1;i<=n;i++)
if(S>=V[i] && d[S-V[i]]+1==d[S])
{
cout<<i<< " ";
print_ans(d, S-V[i]);
break;
}
}
int main()
{
input();
memset(d, -1, sizeof(d));//-1代表没算过
d[0]=0;//0的时候,不需要硬币
int r = dp(S);
if(r==INF) cout<< "no solution"<<endl;
else
{
cout<< r <<endl;
print_ans(d, S);
}
}