bool类型:f[i][j] i这个数额,由j个邮票贴成 是否可行。 f[i][j] = { f[i - p][j - 1] 其中有一个是true即可,p为邮票面额}
换一个思路
f[i] i这个数额,最少由几张邮票组成。
f[i] = min{f[i - p]} + 1 其中i的数额最高可以到达 pk也就是10000*200=2000000的空间和时间其实都是很大了。 再加上每次转移是O(k),还是会TLE。
但是这里我只需要找一些数字,也就是只有用到f[i-p],而在f数组更靠前的地方,其实是用不到那些空间了。那么可以在这里考虑到空间优化,优化到O(10000)的空
间。
这就是无压力可以接受的了。
接下来是转移的问题。
假如有1,2,5 这几个面额。 对于 10而言,可以从9,8,5转移。从f[9] f[8] f[5]找一个最小值。 接下来是从f[6] f[9] f[10]找最小值…… 貌似没有什么可以优化
的,虽然是找最小值,但是并不是区间上的最小值查找,而且不具有连续性,所以貌似不好用堆或者线段树来解决……
最终时间复杂度
换一个思路
f[i] i这个数额,最少由几张邮票组成。
f[i] = min{f[i - p]} + 1 其中i的数额最高可以到达 pk也就是10000*200=2000000的空间和时间其实都是很大了。 再加上每次转移是O(k),还是会TLE。
但是这里我只需要找一些数字,也就是只有用到f[i-p],而在f数组更靠前的地方,其实是用不到那些空间了。那么可以在这里考虑到空间优化,优化到O(10000)的空
间。
这就是无压力可以接受的了。
接下来是转移的问题。
假如有1,2,5 这几个面额。 对于 10而言,可以从9,8,5转移。从f[9] f[8] f[5]找一个最小值。 接下来是从f[6] f[9] f[10]找最小值…… 貌似没有什么可以优化
的,虽然是找最小值,但是并不是区间上的最小值查找,而且不具有连续性,所以貌似不好用堆或者线段树来解决……
最终时间复杂度
2000000 * 50 = 10000000 = 10^8 应该不会TLE。 但是这么不优秀的算法,我实在不开心啊……
Compiling... Compile: OK Executing... Test 1: TEST OK [0.005 secs, 3416 KB] Test 2: TEST OK [0.003 secs, 3416 KB] Test 3: TEST OK [0.003 secs, 3416 KB] Test 4: TEST OK [0.003 secs, 3416 KB] Test 5: TEST OK [0.003 secs, 3416 KB] Test 6: TEST OK [0.000 secs, 3416 KB] Test 7: TEST OK [0.005 secs, 3416 KB] Test 8: TEST OK [0.005 secs, 3416 KB] Test 9: TEST OK [0.008 secs, 3416 KB] Test 10: TEST OK [0.057 secs, 3416 KB] Test 11: TEST OK [0.467 secs, 3416 KB] Test 12: TEST OK [0.100 secs, 3416 KB] Test 13: TEST OK [0.005 secs, 3416 KB] All tests OK.
只用了3M的空间~~~ 这点倒是我很满意的地方啦啦啦啦啦啦啦啦~~~~
/*
TASK:stamps
LANG:C++
*/
#include <cstdio>
#define INF 10000
#define min(a, b) ((a)<(b)?(a):(b))
#define size 13000
int K, N;
int a[50];
int f[size]={0}, now=0, ans=0, tmp, minnum;
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);
for (int i = 1; i != size; ++ i) f[i] = INF;
while (1)
{
++ ans;
++ now;
now %= size;
minnum = INF;
for (int i = 0; i != N; ++ i)
{
tmp = (now - a[i]);
tmp < 0 ? tmp += size : tmp;
if (f[tmp] == INF) continue;
minnum = min(minnum, f[tmp]);
}
if (minnum >= K) break;
f[now] = minnum + 1;
}
printf("%d\n", ans - 1);
return 0;
}