硬币问题有可能是无解的
定义状态d[i] 从i减到0的最少使用的硬币数
可能会无解
下面是代码
//主要问题有:矩阵嵌套问题一开始调用solve(i)的i是怎么确定的? //可以认为是任意一个点吗? //可以认为是任意一个点? //那么如何定义状态? //状态的定义与实际的情况是有关的(有向边是从大到小还是从小到大),但无论怎么,最后的值应该是要打印的那一边的值 //因为这样才可以确定打印的时候的字典序 //当然上面的矩阵嵌套是保证有解的 //回到硬币问题上来 //这个问题不一定有解 //但最后的值必须是在s这边,不应该是在0那边 //所以有两种状态定义的方式:从i出发的最长路,终点到i的最长路 //但是这两种方式的定义又有一些区别(虽然在矩阵嵌套问题上并没有区别) //从s出发的时候不一定是有解的 //递推可以使用的核心是,计算的时候需要使用的数据都已经全部得到了 #include<cstdio> #include<algorithm> using namespace std; //定义状态,d[i]为选用最多的硬币,使得面值之和恰好为i const int maxn = 150; int S = 100; int d[maxn]; int V[] = {2,3,5,7}; int vis[maxn]; int dp(int x) { if(vis[x]) return d[x]; vis[x] = 1; d[x] = 1000; for(int i = 0;i < 4;i++) { if(x >= V[i]) { d[x] = min(d[x],dp(x - V[i]) + 1); } } return d[x]; } void print_ans(int x) { for(int i = 0;i < V[i];i++) { if(d[x] == d[x - V[i]] + 1) { printf("%d ",V[i]); print_ans(x - V[i]); return ; } } } int main() { d[0] = 0; vis[0] = 1; dp(S); print_ans(S); for(int i = 1;i <= S;i++) { d[i] = 1000; for(int j = 0;j < 4;j++) { if(i >= V[j]) { //d[i] = max(d[i],d[i - V[j]] + 1); d[i] = min(d[i],d[i -V[j]] + 1); } } } return 0; }