POJ_1742 Coins (dp)

  第一眼看上去,很明显的母函数嘛。然后巴拉巴拉代码敲出来,TLE。我晕,再看,数据很大。母函数的三重循环会暴掉的,而且仔细想一下,这题相当于染色问题。用母函数的话有很多重复计算的地方。不许要知道凑成面值m时有多少中凑法,只知道可不可达就可以。

  然后看到有人说用《背包九讲》里边提到的单调队列优化的多重背包。然后偶硬生生的啥都没干,用了两天时间看单调队列优化的多重背包。可惜最后结果是没看懂。我觉得原因应该是背包这类dp总的思想理解的不好,以后要好好补补。

   今晚实在受不了,论文看不懂,去找强队。强队说单是这题的话不用单调队列优化。加一个数组就可以O(NV)过。思路是加一个数组cnt[], cnt[j]表示达到面值为j时所用的第i种硬币的个数。所以(0 <= cnt[j] <= c[i])。cnt[j]的转移就是 cnt[j] = cnt[j-a[i]] + 1;(cnt[j]的转移条件是当前的面值j不可达,j-a[i]可达。可以用一个vis[]标记状态)

  然后我稍微改了一下。让cnt[]的初值为c[i],然后每次满足转移条件时cnt[j] = cnt[j-a[i]] - 1;这里cnt[j]就表示达到面值为j时消耗掉第i种硬币若干个后剩余的第i中硬币数。(这样貌似快了一些, 1266+ms)

代码:

1 for(j = 0; j <= V; j++) cnt[j] = c[i];
2 for(j = a[i]; j <= V; j++) {
3 if(!f[j] && f[j-a[i]] && cnt[j-a[i]] > 0) {
4 f[j] = true; ans ++ ;
5 cnt[j] = cnt[j-a[i]] - 1;
6 }
7 }



原文地址:https://www.cnblogs.com/vongang/p/2282765.html