12.动态规划模型
1.最大字段和
//最大字段(连续)和
#include<iostream>
#include<cstdio>
using namespace std;
int n;
int a[105];
int ans=0;
void f1() {
int sum=0;
for(int i=0;i<n;i++){
for(int j=i;j<n;j++){
sum=sum+a[j];
ans=max(ans,sum);
}
sum=0;
}
}
void f2() {
int sum=0;
for(int i=0; i<n; i++) {
int temp=sum+a[i];
if(temp>0) {
sum=sum+a[i];
ans=max(ans,sum);
} else {
sum=0;
}
}
}
int main() {
cin>>n;
for(int i=0; i<n; i++) {
cin>>a[i];
}
f1();//普通写法,O(n2)
f2();//动态规划,O(n)
cout<<ans<<endl;
}
/*
cin:
6
-2 11 -4 13 -5 -2
cout:
20
*/
2.最长上升子序列
//最长上升"子序列"(不连续)
#include<iostream>
#include<cstdio>
using namespace std;
int n,a[105],dp[105];
int ans=0;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=n;i++){
dp[i]=1;
for(int j=1;j<i;j++){
if(a[j]<a[i]){
dp[i]=max(dp[i],dp[j]+1);
}
}
ans=max(ans,dp[i]);
}
cout<<ans<<endl;
return 0;
}
/*
cin:
8
2 1 5 3 6 4 6 3
cout:
4
*/
3.最长公共子序列
//最长公共子序列(不连续)---与求最长公共字段问题进行区分
#include<iostream>
#include<cstring>
using namespace std;
string str1,str2;
int dp[105][105];
int ans=0;
int main() {
cin>>str1>>str2;
memset(dp,0,sizeof(dp));
for(int i=1; i<=str1.size(); i++) {
for(int j=1; j<=str2.size(); j++) {
if(str1[i-1]==str2[j-1]) {
dp[i][j]=dp[i-1][j-1]+1;
}else{
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
}
cout<<dp[str1.size()][str2.size()]<<endl;
return 0;
}
/*
cin:
abcdefgh
acjlfabhh
cout:
4 (a-c-f-h) 不连续的一段
*/
4.编辑距离
//编辑距离
#include<iostream>
#include<cstring>
using namespace std;
int dp[105][105];
string a,b;
int main(){
cin>>a>>b;
int lena=a.size();
int lenb=b.size();
for(int i=1;i<=lena;i++){
dp[i][0]=i;
}
for(int i=1;i<=lenb;i++){
dp[0][1]=i;
}
for(int i=1;i<=lena;i++){
for(int j=1;j<=lenb;j++){
if(a[i-1]==b[i-1]){
dp[i][j]=dp[i-1][j-1];
}else{
dp[i][j]=min(min(dp[i][j-1],dp[i-1][j]),dp[i-1][j-1])+1;
}
}
}
cout<<dp[lena][lenb]<<endl;
return 0;
}
/*
cin:
abcd
acef
cout:
3
*/
5.最大子矩阵和
//最大子矩阵和
#include<iostream>
#include<cstdio>
using namespace std;
long long num[401][401];
long long presum[401][401];
int main(){
int N,M;
long long sum,ans;
cin>>N>>M;
ans=-100000;
for(int i=1;i<=N;i++){
for(int j=1;j<=M;j++){
cin>>num[i][j];
ans=max(ans,num[i][j]);
}
}
if(ans<=0){
cout<<ans<<endl;
}else{
for(int i=1;i<=N;i++){
for(int j=1;j<=M;j++){
presum[i][j]=presum[i-1][j]+num[i][j];
}
}
for(int i=1;i<=N;i++){
for(int j=i;j<=N;j++){
sum=0;
for(int k=1;k<=M;k++){
if(sum+presum[j][k]-presum[i-1][k]<0){
sum=0;
}else{
sum+=presum[j][k]-presum[i-1][k];
}
ans=max(ans,sum);
}
}
}
}
cout<<ans<<endl;
return 0;
}
/*
--cin:
3 3
1 2 3
4 -5 6
7 8 9
--cout:
35
*/
6.环形矩阵
//环形矩阵
//对于环的解题思路可以在环的周围复制一份,例如对于本例题参考上图
#include<iostream>
#include<cstdio>
using namespace std;
int num[91][91];
long long sum[91][91];
int main(){
int n,m;
long long nowsum,ans,t;
cin>>n>>m;
ans=-100000;
for(int i=1;i<=n;i++){
for(int j=0;j<m;j++){
cin>>num[i][j];
if(ans<num[i][j]){
ans=num[i][j];
}
}
}
if(ans<=0){
cout<<ans<<endl;
}else{
for(int i=1;i<=n;i++){
for(int j=0;j<m;j++){
sum[i][j]=sum[i-1][j]+num[i][j];
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
for(int k=0;k<m;k++){
nowsum=0;
for(int l=0;l<m;l++){
if(i<=j){
t=sum[j][(k+l)%m]-sum[i-1][(k+l)%m];
}else{
t=sum[n][(k+l)%m]-(sum[i-1][(k+l)%m]-sum[j][(k+l)%m]);
}
if(nowsum+t<=0){
nowsum=0;
}else{
nowsum+=t;
}
if(ans<nowsum){
ans=nowsum;
}
}
}
}
}
cout<<ans<<endl;
}
return 0;
}
/*
--cin:
3 3
1 -2 3
-4 5 -6
7 -8 9
--cout:
20
*/
7.删除最少的元素
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
int a[1005];
int dp[2][1005];
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
for(int i=0;i<n;i++){
dp[0][i]=1;
for(int j=0;j<i;j++){
if(a[j]>=a[i])
dp[0][i]=max(dp[0][j]+1,dp[0][i]);
}
}
for(int i=n-1;i>=0;i--){
dp[1][i]=1;
for(int j=n-1;j>i;j--){
if(a[j]>=a[i])
dp[1][i]=max(dp[1][i],dp[1][j]+1);
}
}
int ans=0;
for(int i=0;i<n;i++){
ans=max(ans,dp[0][i]+dp[1][i]-1);
}
cout<<n-ans<<endl;
return 0;
}
/*
--cin:
8
2 1 5 3 6 4 6 3
--cot:
3
*/