原题链接
爆搜面值,(DP)判断就好。
一开始打了记搜,结果连(5 5)的数据都过不去。。最后还是老老实实写了(DP),不过还是跑不过(7 5)的数据,但因为这题数据极水,所以轻松过了。
我也去网上翻了翻,目前没有发现哪份代码能真正过满数据,所以就懒得改了。反正能(A)
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 20;
const int M = 1e3;
int f[M], p[N], an[N], ma, n, k;
inline int minn(int x, int y) { return x < y ? x : y; }
int calc(int nw)
{
int i, j, m = p[nw] * n;
memset(f, 60, (m + 1) << 2);
f[0] = 0;
for (i = 1; i <= nw; i++)
for (j = p[i]; j <= m; j++)
f[j] = minn(f[j], f[j - p[i]] + 1);
for (i = 1; i <= m; i++)
if (f[i] > n)
return i - 1;
return m;
}
void dfs(int nw, int m)
{
if (nw > k)
{
if (ma < m)
{
ma = m;
for (int i = 1; i <= k; i++)
an[i] = p[i];
}
return;
}
for (int i = p[nw - 1] + 1; i <= m + 1; i++)//显然最大只能为最大连续值+1,否则肯定不能拼上,而因为每种邮票无限,所以从前种价格+1开搜
{
p[nw] = i;
dfs(nw + 1, calc(nw));//每次DP出最大连续值
}
}
int main()
{
scanf("%d%d", &n, &k);
p[1] = 1;
dfs(2, n);
for (int i = 1; i <= k; i++)
printf("%d ", an[i]);
printf("
MAX=%d", ma);
return 0;
}