第一题:
AC代码:
(1)空间复杂度为O(n^2)的算法:
#include<bits/stdc++.h>
using namespace std;
const int N = 150;
int dp[N][N],a[N][N];
int main(){
int T;
scanf("%d",&T);
while(T--){
memset(dp,0,sizeof(dp));
int r,c;
scanf("%d%d",&r,&c);
for(int i=1;i<=r;i++){
for(int j=1;j<=c;j++){
scanf("%d",&a[i][j]);
dp[i][j]=max(dp[i-1][j],dp[i][j-1])+a[i][j];
}
}
printf("%d\n",dp[r][c]);
}
}
(2)空间复杂度为O(2n)的算法:
#include<bits/stdc++.h>
using namespace std;
const int N = 150;
int dp[2][N],a[N][N];
int main(){
int T;
scanf("%d",&T);
while(T--){
memset(dp,0,sizeof(dp));
int r,c;
scanf("%d%d",&r,&c);
for(int i=1;i<=r;i++){
for(int j=1;j<=c;j++){
scanf("%d",&a[i][j]);
dp[i&1][j]=max(dp[(i&1)^1][j],dp[i&1][j-1])+a[i][j];
}
}
printf("%d\n",dp[r&1][c]);
}
}
(3)空间复杂度为O(n)的算法:
#include<bits/stdc++.h>
using namespace std;
const int N = 150;
int dp[N],a[N][N];
int main(){
int T;
scanf("%d",&T);
while(T--){
memset(dp,0,sizeof(dp));
int r,c;
scanf("%d%d",&r,&c);
for(int i=1;i<=r;i++){
for(int j=1;j<=c;j++){
scanf("%d",&a[i][j]);
dp[j]=max(dp[j],dp[j-1])+a[i][j];
}
}
printf("%d\n",dp[c]);
}
}
第二题:
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 150;
int dp[N],a[N][N];
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
scanf("%d",&a[i][j]);
if(i==1)dp[j]=dp[j-1]+a[i][j];
else if(j==1)dp[j]+=a[i][j];
else dp[j]=min(dp[j],dp[j-1])+a[i][j];
}
}
printf("%d\n",dp[n]);
}
第三题:
解析:
由于当路径重合时i1+j1=i2+j2=k,所以我们可以用k和i表示出一个j
那么分为四种情况:
p1:(i1,j1) p2:(i2,j2)
p1右p2右:(k,i1,i2)
p1下p2右:(k,i1+1,i2)
p1右p2下:(k,i1,i2+1)
p1下p2下:(k,i1+1,i2+1)
由于1<=x<=n&&1<=k-x<=n可以推出x<=k-1&&x>=k-n
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 20;
int dp[N][N][N],a[N][N];
int main(){
int n;
scanf("%d",&n);
int r,c,num;
while(scanf("%d%d%d",&r,&c,&num)){
if(r==0&&c==0&&num==0)break;
a[r][c]=num;
}
for(int k=1;k<=n+n;k++){
for(int i1=max(1,k-n);i1<=k-1;i1++){
for(int i2=max(1,k-n);i2<=k-1;i2++){
int j1=k-i1,j2=k-i2;
if(j1>=1&&j1<=n&&j2>=1&&j2<=n){
int t = a[i1][j1];
if(i1!=i2)t+=a[i2][j2];
int &x=dp[k][i1][i2];
x=max(x,dp[k-1][i1][i2]+t);
x=max(x,dp[k-1][i1-1][i2]+t);
x=max(x,dp[k-1][i1][i2-1]+t);
x=max(x,dp[k-1][i1-1][i2-1]+t);
}
}
}
}
printf("%d\n",dp[n+n][n][n]);
}
第四题:
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 55;
int dp[2*N][N][N],a[N][N];
int main(){
int n,m;
scanf("%d%d",&n,&m);
int r,c,num;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&a[i][j]);
}
}
for(int k=1;k<=n+m;k++){
for(int i1=max(1,k-m);i1<=min(k-1,n);i1++){
for(int i2=max(1,k-m);i2<=min(k-1,n);i2++){
int j1=k-i1,j2=k-i2;
if(j1>=1&&j1<=m&&j2>=1&&j2<=m){
int t = a[i1][j1];
if(i1!=i2)t+=a[i2][j2];
int &x=dp[k][i1][i2];
x=max(x,dp[k-1][i1][i2]+t);
x=max(x,dp[k-1][i1-1][i2]+t);
x=max(x,dp[k-1][i1][i2-1]+t);
x=max(x,dp[k-1][i1-1][i2-1]+t);
}
}
}
}
printf("%d\n",dp[n+m][n][n]);
}