摘花生
状态转移方程:
f[i][j] = max(f[i][j-1],f[i-1][j])+a[i][j];
复杂度 一共有n*n个状态 每个状态由两个转移,时间复杂度O(n2),但是题目中有多个输入,所以接近极限时间了。
#include <iostream>
using namespace std;
const int N = 1e2+10;
int f[N][N];
int a[N][N];
int main() {
int n;
cin>>n;
while(n--){
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]);
}
}
for(int i = 1;i<=r;i++){
for(int j = 1;j<=c;j++){
f[i][j] = max(f[i-1][j],f[i][j-1])+a[i][j];
}
}
cout<<f[r][c]<<endl;
}
return 0;
}
最低通行费
状态转移同上,只是max改min,但是需要初始化
#include <iostream>
using namespace std;
const int N = 1e2+10;
int f[N][N];
int a[N][N];
int main() {
int n;
cin>>n;
for(int i = 1;i<=n;i++){
for(int j = 1;j<=n;j++){
scanf("%d",&a[i][j]);
}
}
for(int i = 1;i<=n;i++) {
f[i][1] = f[i-1][1]+a[i][1];
f[1][i] = f[1][i-1]+a[1][i];
}
for(int i = 2;i<=n;i++){
for(int j = 2;j<=n;j++){
f[i][j] = min(f[i-1][j],f[i][j-1])+a[i][j];
// cout<<f[i][j]<<' ';
}
// cout<<endl;
}
cout<<f[n][n]<<endl;
return 0;
}
方格取数
思路:
可以想象两个人一起走,然后最后当两个人走到B点的时候就是答案,每次两个人一起走的时候要枚举四种状态,然后取最大值。
代码中状态转移写的很清楚:
#include <iostream>
using namespace std;
const int N = 15;
int f[2*N][N][N];
int a[N][N];
int main() {
int n;
cin>>n;
int x,y;
scanf("%d%d",&x,&y);
while(x&&y){
cin>>a[x][y];
scanf("%d%d",&x,&y);
}
for(int i = 1;i<=n;i++){
for(int j = 1;j<=n;j++){
for(int k = 2;k<=2*n;k++){//k的枚举外面还是里面都不会有影响
if(k-i>=1&&k-i<=n&&k-j>=1&&k-j<=n){
if(i==j){
f[k][i][j] = a[i][k-i];
}
else f[k][i][j] = a[i][k-i]+a[j][k-j];
int maxx = -0x3f3f3f3f;
maxx = max(maxx,f[k-1][i][j]);
maxx = max(maxx,f[k-1][i-1][j]);
maxx = max(maxx,f[k-1][i][j-1]);
maxx = max(maxx,f[k-1][i-1][j-1]);
f[k][i][j] +=maxx;
}
}
}
}
cout<<f[2*n][n][n];
return 0;
}
传纸条
题目中与上一题目有不同之处:不能重复走一个格子,但是在最优答案中一定不会走同一个格子,就算能够走同一个各自,那么说明周围的点的值都是0,走别的都一样,所以最后的答案一定是正确的,可用上面题目的coding。
代码:
#include <iostream>
using namespace std;
const int N = 55;
int f[2*N][N][N];
int a[N][N];
int main() {
int n,m;
cin>>n>>m;
for(int i = 1;i<=n;i++){
for(int j = 1;j<=m;j++)
cin>>a[i][j];
}
for(int i = 1;i<=n;i++){
for(int j = 1;j<=n;j++){
for(int k = 2;k<=n+m;k++){
if(k-i>=1&&k-i<=m&&k-j>=1&&k-j<=m){
if(i==j){
f[k][i][j] = a[i][k-i];
}
else f[k][i][j] = a[i][k-i]+a[j][k-j];
int maxx = -0x3f3f3f3f;
maxx = max(maxx,f[k-1][i][j]);
maxx = max(maxx,f[k-1][i-1][j]);
maxx = max(maxx,f[k-1][i][j-1]);
maxx = max(maxx,f[k-1][i-1][j-1]);
f[k][i][j] +=maxx;
}
}
}
}
cout<<f[m+n][n][n];
return 0;
}