算法小记3 前缀和+DP
马上要打蓝桥了,最近超级忙zzz,放平心态吧
1.求区间和
前缀和
难度:普及-
洛谷地址:https://www.luogu.com.cn/problem/P8218
思路:
简单存前缀和,相减
ac代码:
点击查看代码
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define int long long
#define endl '\n'
#define pii pair<int,int>
#define fi first
#define se second
using namespace std;
const int N = 1e5 + 5;
int n,m,a[N],b[N];
signed main() {
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
b[i]=b[i-1]+a[i];
}
cin>>m;
while(m--){
int l,r; cin>>l>>r;
cout<<b[r]-b[l-1]<<endl;
}
return 0;
}
2.最大子段和
DP
难度:普及-
洛谷地址:https://www.luogu.com.cn/problem/P1115
思路:
前缀和+DP,思路是存一个数组,判断遍历到每个i的最大前缀和,注意可能最大是自己
ac代码:
点击查看代码
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define int long long
#define endl '\n'
#define pii pair<int,int>
#define fi first
#define se second
using namespace std;
const int N = 2e5 + 5;
int n,ans=INT_MIN,a[N],b[N];
signed main() {
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++){
b[i]=max(b[i-1]+a[i],a[i]);
ans=max(ans,b[i]);
}
cout<<ans;
return 0;
}
3.领地选择
前缀和+DP
难度:普及-
洛谷地址:https://www.luogu.com.cn/problem/P2004
思路:
二维前缀和,找到DP方程即可求解,注意如果开long long还用INT_MAX会卡测评!
ac代码:
点击查看代码
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define endl '\n'
#define pii pair<int,int>
#define fi first
#define se second
using namespace std;
const int N = 1e3 + 5;
int n,m,c,mx,my,v,mv=INT_MIN,a[N][N],b[N][N];
signed main() {
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n>>m>>c;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
b[i][j]=b[i][j-1]+b[i-1][j]-b[i-1][j-1]+a[i][j];
// cout<<"b:"<<b[i][j]<<endl;
}
}
for(int i=1;i<=n-c+1;i++){
for(int j=1;j<=m-c+1;j++){
v=b[i+c-1][j+c-1]-b[i+c-1][j-1]-b[i-1][j+c-1]+b[i-1][j-1];
if(v>mv){
mv=v;
mx=i,my=j;
}
// cout<<i<<" "<<j<<" "<<v<<endl;
}
}
cout<<mx<<" "<<my;
return 0;
}

浙公网安备 33010602011771号