简单dp = =,没想出来。。
一开始想到用dp[i][j] = 1来表示可以用j张邮票来找i钱。。转移方程为dp[i][j] = 1 if dp[i - coin[k]][j - 1] = 1。
后面发现内存太大存不下。后面发现dp[i][j]只和dp[i - coin[k][j - 1]有关,于是准备用滚动数组去做。做不出来= =。。
看了题解才知道可以用另外一种表示方法dp[i]表示找i钱最少的邮票数,那么转移方程就好简单了。
dp[i] = min(dp[i - coin[k]] + 1);
AC代码:
/* ID: 123 PROG: stamps LANG: C++ */ #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAX_NUMBER = 205; const int INF = 1000000; int coin[MAX_NUMBER]; int dp[MAX_NUMBER * 10000]; int total_number, coin_number; int main() { FILE *in = fopen("stamps.in", "r"); FILE *out = fopen("stamps.out", "w"); fscanf(in, "%d%d", &total_number, &coin_number); for (int i = 1; i <= coin_number; i++) { fscanf(in, "%d", &coin[i]); } sort(coin + 1, coin + 1 + coin_number); for (int i = 1; i <= total_number * coin[coin_number] + 1; i++) { dp[i] = INF; } dp[0] = 0; for (int i = 1; i <= total_number * coin[coin_number]; i++) { for (int j = 1; j <= coin_number; j++) { if (i >= coin[j]) { dp[i] = min(dp[i], dp[i - coin[j]] + 1); } } } int ans = 0; for (int i = 1; i <= total_number * coin[coin_number] + 1; i++) { if (dp[i] > total_number) { ans = i - 1; break; } } fprintf(out, "%d\n", ans); return 0; }