1、这是一道DP,我感觉设计好状态真的很重要,刚开始我的dp【i】是表示“能否凑成数额i”,这就要求一定要等所有面值都算完后,再从头开始搜索看哪个面值不能凑成。比如面值56凑不成,而可能的面值有2000000种,那是巨大的浪费,算法是O(K*K*maxn*N)的,会超时。
2、另一种状态是用dp【i】表示“凑成i最少需要的邮票张数”,这样只要把初始值设为INF,然后从头开始递推即可,一旦不满足要求,立即输出。
3、还有发现gdb的调试功能真的很强大,用wa i+c指令就能在变量i改变的时候自动暂停~我真是太喜欢这个功能啦~
/*
ID:mrxy564
PROG:stamps
LANG:C++
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int INF=~0U>>2;
int a[55],K,N,dp[2000010],maxn=0,minn=INF;
int main(){
freopen("stamps.in","r",stdin);
freopen("stamps.out","w",stdout);
scanf("%d%d",&K,&N);
for(int i=0;i<N;i++){
scanf("%d",&a[i]);
maxn=max(maxn,a[i]);
minn=min(minn,a[i]);
}
for(int i=0;i<=maxn*K+1;i++)
dp[i]=INF;
dp[0]=0;
for(int j=0;j<=maxn*K+1;j++){
for(int k=0;k<N;k++)
if(j>=a[k])
dp[j]=min(dp[j-a[k]]+1,dp[j]);
if(dp[j]>K){
printf("%d\n",j-1);
break;
}
}
return 0;
}
官方题解:
This problem is simply begging for a DP solution. We keep an array "minstamps" such that minstamps[i] is the minimum number of stamps needed to make i cents. For each stamp type, we try adding one stamp of that type to each number of cents that we have already made. After we have found the minimum number of stamps needed to make any given number of cents, we find the smallest number of cents that we cannot make with the given number of stamps, and then we output one less then that.
#include <fstream.h> const int BIG = 10000; short minstamps[10000 * (200 + 3) + 3]; int stamps; int value[200]; int number; int main () { ifstream filein ("stamps.in"); filein >> number >> stamps; int biggest = -1; for (int i = 0; i < stamps; ++i) { filein >> value[i]; if (biggest < value[i]) { biggest = value[i]; } } filein.close (); for (int i = 0; i <= biggest * number + 3; ++i) { minstamps[i] = BIG; } minstamps[0] = 0; for (int i = 0; i < stamps; ++i) { for (int j = 0; j <= biggest * number; ++j) { if (minstamps[j] < number) { if (minstamps[j + value[i]] > 1 + minstamps[j]) { minstamps[j + value[i]] = 1 + minstamps[j]; } } } } int string = 0; while (minstamps[string + 1] <= number) { ++string; } ofstream fileout ("stamps.out"); fileout << string << endl; fileout.close (); return (0); }