題目
試題2:玩具(toy)
源代碼:toy.cpp
輸入文件:toy.in
輸出文件:toy.out
時間限制:1s
空間限制:256MB
題目描述
商店正在出售小C最喜歡的系列玩具,在接下來的n周中,每周會出售其中的一款,同一款玩具不會重復出現。
由於是小C最喜歡的系列,他希望盡可能多地購買這些玩具,但是同一款玩具小C只會購買一個。同時,小C的預算只有m元,因此他無法將每一款都納入囊中。此外,小C不能連續兩周都購買玩具,否則他會陷入愧疚。現在小C想知道,他最多可以買多少款不同的玩具呢?
輸入說明
輸入文件共2行;
第一行兩個正整數n和m,中間用一個空格隔開;
第二行共n個正整數,第i個正整數表示第i周出售的玩具的價格。
輸出說明
輸出文件只有一行,包含一個整數,表示小C最多能買多少款不同的玩具。
樣例輸入
3 8
4 4 5
樣例輸出
1
數據范圍
對於30%的數據,n≤10;
對於60%的數據,n≤100,m≤1000;
對於100%的數據,n≤1000,m≤1000000,單個玩具的價格≤1000。
分析
首先,根據“同一款玩具小C只會購買一個”我們得知大體的做題方向是01背包的DP。
所以我們用f[i]記錄花i塊錢最多能購買到的玩具數量。
但是! 題目中說“不能連續兩周都購買玩具”,所以我們可以打標記避免連續兩周都購買玩具。
粗略的分析完這些,我們就可以寫代碼了!
可惜的是你會發現你無法開下一個n*m的數組去打標記(因為n≤1000,m≤1000000)。
如何縮小一個數組的空間呢?
要么是狀態壓縮,要么是滾動數組。
而現在的情況用滾動數組會更簡單一點。
代碼
#include<iostream> #include<cmath> #include<algorithm> #include<cstdlib> #include<cstdio> using namespace std; int n,m,a[11001]; int f[1100001];//f[i]記錄花i塊錢最多能購買到的玩具數量 bool flag[1100001][3];//f[i][j]記錄f[i]在上周是否購買了玩具(j是用來滾動數組的) int main() { cin>>n>>m; for(int i=1;i<=n;i++) scanf("%d",&a[i]); int o1=1,o2=2; for(int i=1;i<=n;i++) { swap(o1,o2);//滾動一次flag數組 for(int j=0;j<=m;j++) flag[j][o2]=0; for(int j=m;j>=a[i];j--) { if(f[j-a[i]]+1>f[j] && !flag[j-a[i]][o1]) { flag[j][o2]=1; f[j]=f[j-a[i]]+1; } } } cout<<f[m]; return 0; }