描述
有乙個神奇的口袋,總的容積是40,用這個口袋可以變出一些物品,這些物品的總體積必須是40。john現在有n個想要得到的物品,每個物品的體積分別是a
1,a2……a
n。john可以從這些物品中選擇一些,如果選出的物體的總體積是40,那麼利用這個神奇的口袋,john就可以得到這些物品。現在的問題是,john有多少種不同的選擇物品的方式。
輸入輸入的第一行是正整數n (1 <= n <= 20),表示不同的物品的數目。接下來的n行,每行有乙個1到40之間的正整數,分別給出a
1,a2……a
n的值。
輸出輸出不同的選擇物品的方式的數目。
樣例輸入
32020
20
樣例輸出
3
列舉,最大2^20.
遞迴:
#include using namespace std;
int a[30]; int n;
int ways(int w ,int k )
int main()
二維動歸:
#include using namespace std;
int a[30]; int n;
int ways[40][30];//ways[i][j]表示從前j種物品裡湊出體積i的方法數
int main()
ways[0][0] = 1;
for( int w = 1 ; w <= 40; ++ w )
}cout << ways[40][n]; return 0;
}
此問題僅在詢問容積40是否可達,40是個很小的
數,可以考慮對值域空間-即對容積的可達性進行動態
規劃。定義一維陣列 int sum[41];
依次放入物品,計算每次放入物品可達的容積,
並在相應空間設定記錄,最後判斷sum[40] 是否可達
,到達了幾次。
優化:
對於sum[j+input] += sum[j];實際指對於所有滿足sum[j]>0 && j+input <= 40在原有的sum[j+input]基礎上增加sum[j],不斷累積n次。另外,sum[input]++的原因是什麼呢???#include using namespace std;
#define max 41
int main()
cout << sum[40] << endl;
return 0;
}
很容易想到sum[input]++就是儲存input下標位置的值,那麼為什麼不能直接也和其他數一樣通過sum[input] += sum[0];來得到呢,當我們把j最小設為0不是可以麼?也許會有人覺得是這樣,但請回頭看清題意,物品的體積範圍是1-40,也就是說sum[0]恒為0不會發生改變,倘若不特殊處理,那麼每次input下標所對應的位置都將少1.
百練 2755 神奇的口袋
遞迴 include include include includeusing namespace std const int maxn 30 int n,d maxn int dp int w,int n int main 人人為我動歸 狀態定義 揹包容量為i時,選完前j件物品後,能達到該容量的最...
百練 2755 神奇的口袋
第一種解法是很經典的動態規劃,對於值域較小的題目,還可以採用第二種方法,考慮對值域空間 即對容積的可達性進行動態規劃。這道題裡面採用第二種解法還會有空間上的優化。有時把值域作為一種狀態不單單是一種解法,還有可能是唯一的解法。如hdu 1574 rp問題 描述有乙個神奇的口袋,總的容積是40,用這個口...
神奇的口袋(百練2755)
描述 有乙個神奇的口袋,總的容積是40,用這個口袋可以變出一些物品,這些物品的總體積必須是40。john現在有n個想要得到的物品,每個物品的體積分別是a1,a2 an。john可以從這些物品中選擇一些,如果選出的物體的總體積是40,那麼利用這個神奇的口袋,john就可以得到這些物品。現在的問題是,j...