题目大意:可以贴 h 张,有 k 种不同的面额,问如何选择面额能使贴出来的值最大(要求这些值连续)。
如 h=3,k=2 表示可以贴三张,有两种面额。如果这两种面额是 1,4,那么我们可以得到 1,2,3,4,5,6(8,9,12),但是 8 和之前已经不连续了所以最大是6。
如果这两种面额是 1,3,那么我们可以得到 1 到 7 及 9,同样 9 不连续了最大 7。
比较这两种情况我们选择面额 1,3 得到最大连续面额 7。
解题思路:tmp[] 是选择的面额,lim[]是 h 张当面额的和即目前能贴出的最大值,首先一定要有一张 1,因为要求连续,没有 1 的话很多都没法凑,然后去找下一种面额,枚举范围是当前已有面额 +1 到目前能贴出的最大值 +1。递归出口是选择的面额数到达 k,我们去检查一下连续面额,然后 ans 存下最大连续值,as[] 是对应选择的面额。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
int h, k, ans;
int tmp[20], as[20], lim[20];
bool vis[10000];
void check(int now, int sum) {
vis[sum] = true;
if (now == h) return;
for (int i = 0; i < k; i++)
check(now+1, sum+tmp[i]);
}
void dfs(int now) {
if (now == k) {
memset(vis, 0, sizeof(vis));
check(0,0);
int cnt = 0;
while (vis[cnt]) cnt++;
cnt -= 1;
if (cnt > ans) {
ans = cnt;
for (int i = 0; i < k; i++)
as[i] = tmp[i];
}
return;
}
for (int i = tmp[now-1]+1; i <= lim[now-1]+1; i++) {
tmp[now] = i;
lim[now] = i * h;
dfs(now+1);
}
}
int main() {
while (scanf("%d%d", &h, &k) != EOF && h+k) {
tmp[0] = 1;
lim[0] = h;
ans = 0;
dfs(1);
for (int i = 0; i < k; i++)
printf("%3d", as[i]);
printf(" ->%3d\n", ans);
}
return 0;
}