DP阶段测
liu_zheng
·
·
个人记录
DP阶段测总结
P1115 最大子段和
此题比较简单 需要注意的点是 :
题目描述: 选出其中连续且非空的一段使得这段和最大 所以不能跳着找最大字段和 只需要单层循环
代码如下:
#include<bits/stdc++.h>
using namespace std;
int n,a[200020],b[200020];
int main(){
int ans=INT_MIN;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
if(i==1) b[i]=a[i];
else b[i]=max(a[i],b[i-1]+a[i]);
ans=max(ans,b[i]);
}
cout<<ans;
return 0;
}
U523265 怪盗基德的滑翔翼
这题其实就是找最长上升子序列或最长下降子序列 y因为题目描述: “初始时,怪盗基德可以在任何一幢建筑的顶端。他可以选择一个方向逃跑,但是不能中途改变方向(因为中森警部会在后面追击)。因为滑翔翼动力装置受损,他只能往下滑行(即:只能从较高的建筑滑翔到较低的建筑) ”基德可以从任意方向所以最长单调的子序列需要判断
代码如下:
#include<bits/stdc++.h>
using namespace std;
int t;
const int N=100;
int a[N],dp[N];
int n;
int main(){
cin>>t;
while(t--){
cin>>n;
int ans=1;
for(int i=1;i<=n;i++){
cin>>a[i];
dp[i]=1;
}
for(int i=1;i<=n;i++){
for(int j=1;j<i;j++){
if(a[i]>a[j]){
dp[i]=max(dp[i],dp[j]+1);
ans=max(dp[i],ans);
}
}
}
for(int i=1;i<=n;i++)dp[i]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<i;j++){
if(a[i]<a[j]){
dp[i]=max(dp[i],dp[j]+1);
ans=max(dp[i],ans);
}
}
}
cout<<ans<<endl;
}
return 0;
}
P8707 [蓝桥杯 2020 省 AB1] 走方格
这道题基本框架dp 这需要看都dp[i][j]从哪个方向来 题目描述: “只能向右或者向下走 _”所以逆向看就是从上方来或者从左边来;
但是题目有所限制: “注意,如果行号和列数都是偶数,不能走入这一格中” 所以遍历时加个特判判断i和j是否同时为偶数
代码如下:
#include<bits/stdc++.h>
using namespace std;
int n,m;
int dp[35][35];
int main(){
cin>>n>>m;
dp[1][1]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(i==1&&j==1)continue;
if(i%2==0&&j%2==0)continue;
dp[i][j]=dp[i][j-1]+dp[i-1][j];
}
}
cout<<dp[n][m];
return 0;
}
P6208 [USACO06OCT] Cow Pie Treasures G
这道题方向多了些可以斜着走 并且逆向找的时候可能越界特判就行 逆向时j的下标都得-1 所以j==1时会越界continue就行 并且n和m找的时候需要倒着遍历且i不能大于j
代码如下:
#include<bits/stdc++.h>
using namespace std;
int n,m;
long long dp[105][105],a[105][105];
int t;
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
}
}
dp[1][1]=a[1][1];
for(int j=1;j<=m;j++){
for(int i=1;i<=n;i++){
if(i==1&&j==1)continue;
if(i>j)continue;
if(i==1){
dp[i][j]=max(dp[i+1][j-1],dp[i][j-1])+a[i][j];
continue;
}
if(j==1)continue;
dp[i][j]=max(dp[i+1][j-1],max(dp[i][j-1],dp[i-1][j-1]))+a[i][j];
}
}
cout<<dp[n][m];
return 0;
}
P7158 「dWoi R1」Password of Shady
n=1时 0<=x<=9 肯定输出9 并且此题需要开long long 不开会爆
状态转移方程:f[i]=f[i−1]×9+g[i−1]
状态转移:g[i]=g[i−1]×9+f[i−1]
代码如下:
#include<bits/stdc++.h>
using namespace std;
int n;
int t,k;
const int N=1e6+10;
long long dp1[N],dp2[N];
int main(){
cin.tie(0);
cout.tie(0);
cin>>t;
dp1[1]=1;
dp2[1]=8;
for(int i=2;i<=100000;i++){
dp1[i]=(dp1[i-1]*9+dp2[i-1]*1);
dp2[i]=(dp2[i-1]*9+dp1[i-1]*1);
dp1[i]%=998244353;
dp2[i]%=998244353;
}
while(t--){
cin>>n>>k;
if(n==1){
cout<<9<<"\n";
continue;
}
cout<<dp2[n]<<"\n";
}
return 0;
}
P2871 [USACO07DEC] Charm Bracelet S
此题dp背包模板
代码如下:
#include<bits/stdc++.h>
using namespace std;
int n,m;
const int N=12889;
int dp[N],w[N],d[N];
int main(){
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>w[i]>>d[i];
}
for(int i=1;i<=n;i++){
for(int j=m;j>=w[i];j--){
dp[j]=max(dp[j],dp[j-w[i]]+d[i]);
}
}
cout<<dp[m];
return 0;
}
P2677 [USACO07DEC] Bookshelf 2 B
此题也dp模板但求的是背包中奶牛的高度所求却时 “奶牛们叠成的塔最少比书架高的高度” 所以最后用牛的总高度减去放入背包中牛的高度再减去书架高度
代码如下:
#include<bits/stdc++.h>
using namespace std;
int ans;
int n,b,h[100000];
int w[100000];
int c;
int main(){
cin>>n>>b;
for(int i=1;i<=n;i++)
{
cin>>w[i];
ans+=w[i];
}
c=ans-b;
for(int i=1;i<=n;i++)
{
for(int j=c;j>=w[i];j--)
{
h[j]=max(h[j],h[j-w[i]]+w[i]);
}
}
cout<<ans-h[c]-b;
return 0;
}
P1510 精卫填海
状态转移:f[j]=max(f[j],f[j-w[i]]+v[i])
此题01背包 判断能否填满即可
代码如下:
#include<bits/stdc++.h>
using namespace std;
int v,n,c;
const int N=1e4+10;
int k[N],m[N],dp[N];
int main(){
// freopen("T8.in","r",stdin);
// freopen("T8.out","r",stdout);
cin>>v>>n>>c;
for(int i=1;i<=n;i++){
cin>>k[i]>>m[i];
}
for(int i=1;i<=n;i++){
for(int j=c;j>=m[i];j--){
dp[j]=max(dp[j],dp[j-m[i]]+k[i]);
}
}
for(int i=0;i<=c;i++){
if(dp[i]>=v){
cout<<c-i<<endl;
return 0;
}
}
cout<<"Impossible"<<endl;
return 0;
}