【USACO3.1.6】邮票 动态规划/滚动数组

来源:互联网 发布:天天网络电视apk破解版 编辑:程序博客网 时间:2024/05/16 15:04
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]找最小值…… 貌似没有什么可以优化


的,虽然是找最小值,但是并不是区间上的最小值查找,而且不具有连续性,所以貌似不好用堆或者线段树来解决……


最终时间复杂度

2000000 * 50 = 10000000 = 10^8  应该不会TLE。 但是这么不优秀的算法,我实在不开心啊……



Compiling...Compile: OKExecuting...   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:stampsLANG:C++*/#include <cstdio>#define INF 10000#define min(a, b) ((a)<(b)?(a):(b))#define size 13000int 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;}


0 0
原创粉丝点击