动态规划DP
总的:当涉及i-1,j-1时,坐标一般从1开始
三大模型之一 背包问题(组合模型)
DP一般解决Min/Max/Count问题,以背包问题为例分析 ,看下一步选还是不选,这是
例题:背包问题
#include<iostream>
using namespace std;
const int N=1005;
int n,m;
int f[N],v[N],w[N];
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>v[i]>>w[i];
for(int i=1;i<=n;i++)
for(int j=m;j>=0;j--)
{
if(j<v[i])
f[i][j]=f[i-1][j];
else
f[j]=max(f[i]][j],f[j-v[i]]+w[i]);
}
cout<<f[m]<<endl;
return 0;
}
三大模型之二 二维线性DP
看每一步操作有哪些方案,摘花生这题就是看走一步是向南走还是先东走,这是两种方案
例题:摘花生
#include<iostream>
#include<algorithm>
using namespace std;
const int N=110;
int w[N][N],f[N][N];
int r,c;
int main()
{
int t;
cin>>t;
while(t--)
{
//读数据
cin>>r>>c;
for(int i=1;i<=r;i++)
{
for(int j=1;j<=c;j++)
{
cin>>w[i][j];
}
}
//处理动态数组f[N][N]
for(int i=1;i<=r;i++)
{
for(int j=1;j<=c;j++)
{
f[i][j]=max(f[i-1][j]+w[i][j],f[i][j-1]+w[i][j]);
}
}
//输出结果
cout<<f[r][c]<<endl;
}
return 0;
}
第二个线性DP 乌龟棋ACWing
#include<iostream>
#include<algorithm>
using namespace std;
const int N=360;
int f[41][41][41][41];
int w[N],s[5];
int n,m;
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>w[i];
while(m--)
{
int x;
cin>>x;
s[x]++;
}
//处理边界问题,一步都不走就在第一格,所以只有第一个的分数
f[0][0][0][0]=w[1];
//枚举状态
for(int A=0;A<=s[1];A++)
{
for(int B=0;B<=s[2];B++)
{
for(int C=0;C<=s[3];C++)
{
for(int D=0;D<=s[4];D++)
{
int score=w[A*1+B*2+C*3+D*4+1];//记得加1
if(A) f[A][B][C][D]=max(f[A][B][C][D],f[A-1][B][C][D]+score);//如果还有A,那么就比较最大值
if(B) f[A][B][C][D]=max(f[A][B][C][D],f[A][B-1][C][D]+score);
if(C) f[A][B][C][D]=max(f[A][B][C][D],f[A][B][C-1][D]+score);
if(D) f[A][B][C][D]=max(f[A][B][C][D],f[A][B][C][D-1]+score);
}
}
}
}
cout<<f[s[1]][s[2]][s[3]][s[4]]<<endl;
return 0;
}
三大模型之三 最长上升子序列(一维线性DP)