標籤:style blog http color io for div html
http://poj.org/problem?id=1742
題意:
很多硬幣,有價值和數量,給出一個上限,問上限內有多少種錢數可以由這些硬幣組成。
分析:
好像是樓教主男人八題之一。然後學多重背包單調隊列最佳化時看了別人的程式。。所以後來寫了就1A了=。=
前一篇小小總結了一下多重背包單調隊列最佳化(http://www.cnblogs.com/james47/p/3894772.html),這裡就不寫了。
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 5 int n, m, head, tail; 6 int a[150], c[150]; 7 int q[(int)1e5+100]; 8 bool dp[(int)1e5+100]; 9 int main()10 {11 while(scanf("%d %d", &n, &m) && (n+m))12 {13 for (int i = 0; i < n; i++)14 scanf("%d", a+i);15 for (int i = 0; i < n; i++)16 scanf("%d", c+i);17 memset(dp, 0, sizeof(dp));18 dp[0] = true;19 for (int i = 0; i < n; i++){20 int maxl = a[i] * c[i];21 if (c[i] == 1){22 for (int j = m; j >= a[i]; j--)23 if (dp[j - a[i]]) dp[j] = true; 24 }25 else if (m <= maxl){26 for (int j = a[i]; j <= m; j++)27 if (dp[j - a[i]]) dp[j] = true; 28 }29 else for (int j = 0; j < a[i]; j++){ //迴圈a[i]的同餘類30 head = tail = 0;31 for (int k = j; k <= m; k += a[i]){32 while (head != tail && k - q[head] > maxl) head++; //這題單調隊列元素優劣性只取決於位置33 if (!dp[k]){ //只需踢掉前面已經超出長度的,即第i個硬幣全用了也不能由它轉移到當前值k34 if (head != tail) //單調隊列裡有元素,可以被他們最佳化35 dp[k] = true;36 }37 else q[tail++] = k; //dp[k]為真,可以最佳化後面的值,放入隊列38 }39 }40 }41 int ans = 0;42 for (int i = 1; i <= m; i ++)43 if (dp[i]) ans ++;44 printf("%d\n", ans);45 }46 return 0;47 }