Educational DP Contest を解く
どうも,『アルゴリズム理論の基礎』でアルゴリズムを初めて勉強しているshadeです。 まだ読了できていませんが,競技プログラミングでは頻出(多分)の動的計画法(DP)について一通り勉強したので,アウトプットも兼ねてAtCoderの「Educational DP Contest / DP まとめコンテスト」の問題を解いていきたいと思います。
順次解いた問題は追加されます。
コンテストページはこちら atcoder.jp
A - Frog1
方針
足場 から足場 に辿り着くまでのコストの総和の最小値を ,足場 から足場 に行くためのコストを ,足場 から足場 に行くためのコストを と表すと, であり,足場 の直前は足場 , のいずれかであるから,一般に,
です。 の値を増加させながらこれを計算し, を求めます。
コード
#include <bits/stdc++.h> using namespace std; int main(){ int n; cin>>n; vector<int> h(n); for(int i=0; i<n; i++){ cin>>h[i]; } vector<int> m(n),a(n),b(n); a[0]=0,b[0]=0,m[0]=0; a[1]=abs(h[0]-h[1]),b[1]=0,m[1]=a[1]; for(int i=2; i<n; i++){ a[i]=abs(h[i-1]-h[i]); b[i]=abs(h[i-2]-h[i]); m[i]=min(m[i-1]+a[i],m[i-2]+b[i]); } cout<<m[n-1]<<endl; }
C - Vacation
方針
日目までの幸福度の総和の最大値を とします。ここで, 日目までの幸福度の総和について, 日目にA,B,Cを選んだ場合の最大値をそれぞれ とすると,明らかに,{} です。さらに,2日連続で同じ選択はできないので, 日目には 日目とは異なる選択をしています。つまり,
です。この計算を繰り返して を求めます。
コード
#include <bits/stdc++.h> using namespace std; int main(){ int n; cin>>n; vector<int> a(n),b(n),c(n); for(int i=0; i<n; i++){ cin>>a[i]>>b[i]>>c[i]; } vector<int> x(n),y(n),z(n); x[0]=a[0],y[0]=b[0],z[0]=c[0]; for(int i=1; i<n; i++){ x[i]=max(y[i-1],z[i-1])+a[i]; y[i]=max(z[i-1],x[i-1])+b[i]; z[i]=max(x[i-1],y[i-1])+c[i]; } cout<<max(max(x[n-1],y[n-1]),z[n-1])<<endl; }
D - Knapsack1
方針
ナップサックの容量を ,品物を としたとき,持ち帰る品物の価値の総和の最大値を とします。(i)品物 を選ばないとき,価値の総和の最大値は,品物が である場合の最大値と等しく,(ii)品物 を選ぶとき,価値の総和の最大値は,ナップサックの容量が (品物 の分を開けておく),品物が である場合の最大値に を加えたものに等しいので,
と表せます。 は負にはなれないので注意が必要です。求める最大値は, です。
コード
#define _GLIBCXX_DEBUG #include <bits/stdc++.h> using namespace std; int main(){ int n,W; cin>>n>>W; vector<int> w(n),v(n); for(int i=0; i<n; i++){ cin>>w[i]>>v[i]; } vector<vector<long>> M(W,vector<long>(n)); for(int i=0; i<W; i++){ if(i+1>=w[0]){ M[i][0]=v[0]; }else{ M[i][0]=0; } } for(int i=0; i<W; i++){ for(int j=1; j<n; j++){ if(i-w[j]<0){ M[i][j]=M[i][j-1]; }else{ M[i][j]=max(M[i][j-1],M[i-w[j]][j-1]+v[j]); } } } cout<<M[W-1][n-1]<<endl; }