[USACO12OPEN]Bookshelf S
阿新 • • 發佈:2021-09-09
題目大意
有 \(N\) 本書,第 \(i\) 本書寬 \(w_i\),高 \(h_i\)。
我們需要將這些這些書分成幾個區間,每個區間所有書的寬度之和不超過 \(L\)。
書架的高度為每個區間最高的書的高度之和,求書架最小高度。
題目分析
我們令 \(dp[i]\) 表示到第 \(i\) 本書為止,書架的最小高度。
對於每一個狀態 \(dp[i]\),都可能由兩種方法轉移而來:
- 再開一個書架。此時有
\(h[i]\) 表示每一本書的高度。
- 插入之前的書架,那麼當然需要知道前面數的最大高度,\(O(N)\) 查詢即可。有
\(\operatorname{maxsum}\)
程式碼
//2021/9/6 //2021/9/8 #include <iostream> #include <cstdio> #include <algorithm> #define debug(c) cerr<<#c<<" = "<<c<<endl namespace Newstd { inline int read() { char c; bool flag=false; while((c=getchar())<'0' || c>'9') { if(c=='-') flag=true; } int res=c-'0'; while((c=getchar())>='0' && c<='9') { res=(res<<3)+(res<<1)+c-'0'; } return flag?-res:res; } inline void print(int x) { if(x<0) { putchar('-');x=-x; } if(x>9) { print(x/10); } putchar(x%10+'0'); } } using namespace Newstd; using namespace std; const int ma=100005; int h[ma],w[ma],sum[ma],dp[ma]; int n,m; int main(void) { n=read(),m=read(); for(register int i=1;i<=n;i++) { h[i]=read(),w[i]=read(); sum[i]=sum[i-1]+w[i]; dp[i]=(1<<29); } for(register int i=1;i<=n;i++) { dp[i]=dp[i-1]+h[i]; int tmp=h[i]; for(register int j=i-1;j>=1 && sum[i]-sum[j-1]<=m;j--) { tmp=max(tmp,h[j]); dp[i]=min(dp[i],dp[j-1]+tmp); } } print(dp[n]); return 0; }