😺
ABC204 D-Cooking(C++)
問題概要
問題文
料理
から 1 の N 品の料理を作る。 N
料理は、オーブンを連続して i 分間使うことで作れる。 T_i つのオーブンを 1 つ以上の料理のために同時に使うことはできない。 2
つのオーブンを使えるとき、 2 品の料理を全て作るまでに最短で何分かかるか? N
制約
1\leq N\leq 100 1\leq T_i\leq 10^3 - 入力はすべて整数
問題リンク
解法
言い換えると、次の通り。
-
と分割する\{1,2,\dots,N\}=X \cup Y -
を最小化せよ。\max(\sum_{i\in X}{T_i},\sum_{i\in Y}{T_i})
以下
この問題の重要なポイントとして、
もっと言うと、
まとめると、次のようにすればいいです。
- あらかじめ、
についての部分和問題を解いておく。T -
に対して、以下を繰り返すS_X=0,1,\dots,S -
- 対応する
が存在しなければスキップX
- 対応する
-
-
について、S_Y=S-S_X と更新するans=\min(ans,\max(S_X,S_Y))
-
実装
計算量
main.cpp
#include<iostream>
#include<vector>
using namespace std;
int main(){
int n;
cin>>n;
vector<int> t(n);
for(int i=0;i<n;i++)cin>>t[i];
int S=0;
for(int i=0;i<n;i++)S+=t[i];
//部分和問題を解いておく
//dp[i][j]:=先頭i項をみる。いくつか選んで和をjにできるか?
vector<vector<bool>> dp(n+1,vector<bool>(S+1,false));
dp[0][0]=true;
for(int i=0;i<n;i++)for(int j=0;j<=S;j++){
if(!dp[i][j])continue; //dp[i][j]=falseなら、dp[i][j]からの遷移は起きない
dp[i+1][j]=true; //t_iを選ばない場合
dp[i+1][j+t[i]]=true; //選ぶ場合
}
const int inf=1e9;
int ans=inf;
for(int sx=0;sx<=S;sx++){
if(!dp[n][sx])continue; //作れないならcontinue
int sy=S-sx;
int time=max(sx,sy); //全体でかかる時間
ans=min(ans,time);
}
cout<<ans<<endl;
}
Discussion