1. 程式人生 > >動態規劃_百煉4120 硬幣

動態規劃_百煉4120 硬幣

amp 使用 兩種 部分 新的 tor color 不能 blog

 1 #define _CRT_SECURE_NO_WARNINGS  
 2 #include <stdio.h>
 3 #include <math.h>
 4 #include <algorithm>
 5 #include <stdlib.h>
 6 #include <vector>
 7 #include <map>
 8 #include <queue>
 9 #include <string>
10 #include <iostream>
11 #include <ctype.h>
12
#include <string.h> 13 #include <set> 14 #include <stack> 15 #include<functional> 16 using namespace std; 17 #define size 100001 18 #define maxn 1<<30 19 int dp[size]; 20 int dpn[size]; 21 int a[205], ans[205]; 22 /* 23 dp是一個滾動數組dp[j]表示j塊錢可以用錢幣組成的數目 24 dpn也是一個滾動數組表示不用第i種錢可以組成j塊錢的數目
25 dp[j]=dp[j]+dp[j-a[i]] 26 有兩種可能性,一種是不用第i個錢幣,那麽他的數目就等於dp[i-1][j] 也就是dp[j] 27 意思是使用第i個錢幣,那麽他的數目就等於dp[j-a[i]]; 28 dp[0]=1; 其他初始化為0; 29 30 31 當可以選第i件錢幣時 32 dpn[j]=dp[j]-dpn[j-a[i]] 33 當j-a[i]<0 34 那本來就不能選擇第i個錢幣 35 dpn[j]=dp[j] 36 37 出口dpn[0]=1 當j==a[i]時會出現也就是說,把單獨這一個情況排除就好,也就是減去1種只有這一個錢幣組成的情況
38 39 40 註意兩次更新的內層循環的順序 41 */ 42 int main(){ 43 44 int n, x; 45 cin >> n >> x; 46 for (int i = 1; i <= n; i++){ 47 scanf("%d", &a[i]); 48 } 49 dp[0] = dpn[0] = 1; 50 for (int i = 1; i <= n; i++) 51 for (int j = x; j >= a[i]; j--){ 52 dp[j] = dp[j] + dp[j - a[i]];//因為實際上需要的是dp[i-1][j] 那麽內層循環要倒序更新 53 } 54 int pos = 0; 55 for (int i = 1; i <= n; i++) 56 { 57 for (int j = 0; j <=x; j++){ 58 if (j - a[i] >= 0) 59 dpn[j] = dp[j] - dpn[j - a[i]];//因為不是滾動數組沒有倒序更新的必要了 60 else 61 dpn[j] = dp[j];//而且應該是先填充dpn[j]較小的部分,要是倒序更新,第一遍dpn[j-a[i]]等於1,0,0,0 並不是我們所需要的dpn[j] 62 } 63 if (dpn[x] == 0) ans[pos++] = a[i]; 64 } 65 cout << pos << endl; 66 if(pos) cout << ans[0]; 67 else cout <<endl; 68 for (int i = 1; i < pos; i++) 69 cout << " "<<ans[i]; 70 cout << endl; 71 system("pause"); 72 return 0; 73 }

動態規劃_百煉4120 硬幣