DPのいくつかの一般的なタイプ。
1.パスDP。
例1.P1216 [USACO1.5] [IOI1994]デジタル三角数
タイトルポータル
選択された各パス2点のみ、よく書かれたDP、コードの以下の詳細な説明を参照するタイトル。
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+5;
int n,dp[N][N],a[N][N];//状态的确立:dp[i][j]表示终点为第i行第j列的最大值
int main(){
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=i;j++)
{
cin>>a[i][j];
if(i==n) //确立初始状态:即最后一行的状态.
dp[i][j]=a[i][j];
**加粗样式** }
for(int i=n-1;i>=1;i--)//从下往上递推
for(int j=1;j<=i;j++)
dp[i][j]=max(dp[i+1][j]+a[i][j],dp[i+1][j+1]+a[i][j]);//每个点只能从由下一行的左边一个点或者右边一个点走到
cout<<dp[1][1]<<endl;//反过来想:起点为(1,1)的最大路径 倒过来走终点必为 (1,1)
return 0;
}
単純な再帰DP。
P2837 [USACO08FEB]食事牛B
DP [i]は、私が修正する前に牛の最小数であると仮定します。
議論のためのI-牛の。もしiが管理していない最初の牛2:DP [I] = DP [ iが-1]、 I-1および牛は、2つのケースに分けられる場合:1.変更されない場合、DP [i]はフロント2に等しいです。変更したい場合数は、2.、DPに等しい[I-1] +1は、 CNTが空間はO(1)に圧縮することができるように、DP [I]は、前の状態から得られるため、一次元であってもよいです。次のコードを参照してください。
#include<bits/stdc++.h>
using namespace std;
int ans,cnt,n,x;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>x;
x==2?cnt++:ans=min(ans+1,cnt);
}
cout<<ans<<endl;
return 0;
}
ステート型DP
P1877 [HAOI2012]ボリュームコントロール
セットDP [I] J Iの曲の音量を達することができるの[J]、
DP [I] [J] = 1はこの状態を示しそうでなければ到達し、そして最後に再度粗下降掃引することができない0に到達します。
#include<bits/stdc++.h>
using namespace std;
int dp[1005][1005],a[55];
int main(){
int n,st,mx;
cin>>n>>st>>mx;
for(int i=1;i<=n;i++) cin>>a[i];
dp[0][st]=1;
for(int i=1;i<=n;i++)
for(int j=0;j<=mx;j++)
{
if(dp[i-1][j]&&a[i]+j<=mx) dp[i][a[i]+j]=1;
if(dp[i-1][j]&&j-a[i]>=0) dp[i][j-a[i]]=1;
}
for(int i=mx;i>=0;i--)
if(dp[n][i])
{
printf("%d\n",i);
return 0;
}
puts("-1");
return 0;
}