hdu 5616 Jam's balance 正反揹包+轉換

http://acm.hdu.edu.cn/showproblem.php?pid=5616php

思路

題目中蘊含着兩種須要計算的重量ios

1. 從全部的砝碼中挑出任意種
2.(轉換的思想)在天平的兩端都挑出這些砝碼中的一些,它也能夠計算出差值,這個差值也是一種重量
    這其實一種轉換,看下面這個公式(左端砝碼的重量)==(右端砝碼的重量+能計算出的重量G)
    當第一次選擇一個砝碼,咱們計算出了以第二種方式的一種重量G,那麼它也要被記爲true,它還能夠
    繼續更新出新的重量,G(新的左端砝碼重量)=(右端砝碼的重量+能計算出的重量)
    那麼上述的過程就是一個從揹包裏取出東西的過程。
    在代碼裏有詳細的分析。
揹包正反各來一遍數組

代碼:優化

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<algorithm>
 6 #define MAXN 2005
 7 using namespace std;
 8 int w[MAXN];
 9 bool dp[MAXN];//滾動數組,只要一維,內存優化
10 int main()
11 {
12     int t,n,q,k;
13     scanf("%d",&t);
14     while(t--)
15     {
16         scanf("%d",&n);
17         for(int i = 0;i<n;i++)
18         {
19             scanf("%d",&w[i]);
20         }
21         memset(dp,false,sizeof(dp));
22         dp[0] = true;
23         //positive
24         //正着來一次揹包,按階段每一次添加一個
25         for(int i = 0;i<n;i++)
26         {
27             //每一次選擇當前這個砝碼,j表示的是當前能夠稱出來的重量
28             //j-w[i]表示前一輪該重量是否有
29             for(int j = MAXN;j>=w[i];j--)
30             {
31                 dp[j]|=dp[j-w[i]];
32             }
33             
34             //必須倒着來,若是正着來錯誤!!
35             /*
36                   for(int j = 0;j<=MAXN-w[i];j++)
37                 {
38                     dp[j+w[i]]|=dp[j];
39                 }
40                 在這一次循環中用到了本輪已更新的結果,咱們只能用前一輪的結果
41                 這樣會出現的錯誤是一輪中加了n個w[i],並且在本輪中加了n個,毫無疑問!
42             */
43         }
44         
45         //negative
46         //逆着來一遍,從揹包中取出東西
47         for(int i = 0;i<n;i++)
48         {
49             //按照個人題解就是每一次選中當前的這個砝碼做爲右端砝碼
50             //j表示左端減去右端的重量
51             //也許你要理解的是每一次你只選一個,這樣的話要是右端放多個不也行嗎
52             //可是你要知道你每一輪的新重量實際上是保留下來了(更新了)
53             //因此下一輪中用了前一個砝碼的新重量你還能夠用(也就是再減一個砝碼)
54             for(int j = 0 ; j<=MAXN-w[i] ; j++)
55             {
56                 dp[j]|=dp[j+w[i]];
57             }
58             
59              //必須正着來,若是倒着來也錯誤!!
60             /*
61                   for(int j = MAXN-w[i];j>=0;j--)
62                 {
63                     dp[j-w[i]]|=dp[j];
64                 }
65                 在這一次循環中用到了本輪已更新的結果,咱們只能用前一輪的結果
66                 這樣會出現的錯誤是一輪中減了n個w[i],並且在本輪中減了n個,毫無疑問!
67             */
68         }
69         scanf("%d",&q);
70         for(int i = 1;i<=q;i++)
71         {
72             scanf("%d",&k);
73             if(dp[k])
74                 printf("YES\n");
75             else
76                 printf("NO\n");
77         }
78     }
79     return 0;
80 }
相關文章
相關標籤/搜索