0、总览
1、摘花生
//最大值,f[][]没有做任何初始化
#include<iostream>
#include<cstring>
using namespace std;
int n;
const int N=110;
int f[N][N];
int g[N][N];
int main()
{
scanf("%d",&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",&g[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])+g[i][j];
printf("%d\n",f[r][c]);
//不需要初始化,因为每一组数据都将上一组数据覆盖
//memset(f,0,sizeof f);
//memset(g,0,sizeof g);
}
return 0;
}
2、最低通行费
#include<iostream>
using namespace std;
const int N=110,INF=1e9;
int w[N][N];
//到nn位置的最小费用
int f[N][N];
int n;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
scanf("%d",&w[i][j]);
//最小值,需要处理边界问题,赋值正无穷
f[i][j]=INF;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(i==1&&j==1) f[i][j]=w[i][j];
else
{
if(i>1) f[i][j]=min(f[i][j],f[i-1][j]+w[i][j]);
if(j>1) f[i][j]=min(f[i][j],f[i][j-1]+w[i][j]);
}
}
printf("%d",f[n][n]);
return 0;
}
3、方格取数
可以经过同一个点,但是数值已经变为0,不能取方格数。
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 15;
int n;
int w[N][N];
int f[N * 2][N][N];
int main()
{
scanf("%d", &n);
int a, b, c;
while (cin >> a >> b >> c, a || b || c) w[a][b] = c;
//左上角是1,1 k=2
for (int k = 2; k <= n + n; k ++ )
for (int i1 = 1; i1 <= n; i1 ++ )
for (int i2 = 1; i2 <= n; i2 ++ )
{
int j1 = k - i1, j2 = k - i2;
if (j1 >= 1 && j1 <= n && j2 >= 1 && j2 <= n)
{
int t = w[i1][j1];
if (i1 != i2) t += w[i2][j2];
int &x = f[k][i1][i2];
//下下
x = max(x, f[k - 1][i1 - 1][i2 - 1] + t);
//下右
x = max(x, f[k - 1][i1 - 1][i2] + t);
//右下
x = max(x, f[k - 1][i1][i2 - 1] + t);
//右右
x = max(x, f[k - 1][i1][i2] + t);
}
}
printf("%d\n", f[n + n][n][n]);
return 0;
}
#include<iostream>
#include<algorithm>
using namespace std;
int n;
const int N=15;
int w[N][N];
int f[N+N][N][N];
int main()
{
scanf("%d",&n);
int a,b,c;
while(cin>>a>>b>>c,a||b||c) w[a][b]=c;
for(int k=2;k<=2*n;k++)
for(int i1=max(1,k-n);i1<=min(n,k-1);i1++)
for(int i2=max(1,k-n);i2<=min(n,k-1);i2++)
for(int a=0;a<=1;a++)
for(int b=0;b<=1;b++)
{
int t=w[i1][k-i1];
if(i1!=i2) t+=w[i2][k-i2];
f[k][i1][i2]=max(f[k][i1][i2],f[k-1][i1-a][i2-b]+t);
}
printf("%d",f[2*n][n][n]);
return 0;
}
4、传纸条
不能经过同一个点
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 55;
int n, m;
int g[N][N];
int f[N * 2][N][N];
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= m; j ++ )
scanf("%d", &g[i][j]);
//初始化不用做,所有的数据均为正数,又是取最大值,声明后即为0
for (int k = 2; k <= n + m; k ++ )
for (int i = max(1, k - m); i <= min(n,k-1); i ++ )
for (int j = max(1, k - m); j <=min(n,k-1) ; j ++ )
for (int a = 0; a <= 1; a ++ )
for (int b = 0; b <= 1; b ++ )
{
int t = g[i][k - i];
if (i != j || k == 2 || k == n + m) // 除了起点和终点之外,其余每个格子只能走一次
{
t += g[j][k - j];
f[k][i][j] = max(f[k][i][j], f[k - 1][i - a][j - b] + t);
}
}
//k=x+y i,j->x1,x2
printf("%d\n", f[n + m][n][n]);
return 0;
}