邮票组合问题
有四种面值的邮票很多枚,面值分别为1,4,12,21,取五张,求取出这些邮票的最大连续组合值
代码:
#include <stdio.h> #include <string.h>
#define N 5 #define M 5 int k, Found, Flag[N]; int Stamp[M] = {0, 1, 4, 12, 21};
// 在剩余张数n中组合出面值和Value int Combine(int n, int Value) { if(n >= 0 && Value == 0) { Found = 1; int Sum = 0; for(int i=0; i<N && Flag[i] != 0; i++) { Sum += Stamp[Flag[i]]; printf("%d ", Stamp[Flag[i]]); } printf(" Sum=%d ", Sum); } else {
for(int i=1; i<M && !Found && n>0; i++) if(Value-Stamp[i] >= 0) { Flag[k++] = i; Combine(n-1, Value-Stamp[i]); Flag[--k] = 0; }
} return Found; }
int main(int argc, char* argv[]) { for(int i=1; Combine(N, i); i++, Found=0); }
改进算法:
#include <iostream> #include <string.h> using namespace std; #define MAX 10 #define MAXINT 100000 #define min(a, b) ((a) >= (b) ? (b) : (a)) int Stamp[MAX+1]; int StampCnt[MAXINT] = {0}; int MaxValue(int n, int m) { int i, j; for(i = 1; ; i++) { StampCnt[i] = 201; for(j = 1; j <= m; j++) { if(Stamp[j] == i) { StampCnt[i] = 1; break; } else if(i > Stamp[j]) { StampCnt[i] = min(StampCnt[i], StampCnt[i-Stamp[j]] + 1); } } if(StampCnt[i] > n) return i-1; } // return 0; } int main() { int N, M; int i, j; cin >> N >> M; //5 5, 输入 1 2 4 12 21, 输出 71 memset(Stamp, 0, sizeof(Stamp)); for(i = 1; i <= M; i++) { cin >> Stamp[i]; } cout << MaxValue(N, M) << endl; }