算法一:前向后向深搜(只通过一个,其余超时)
#include<iostream>
#include<cstring>
using namespace std;
void dfsFront(int fx, int fy); // 起点到终点前向深度搜索
void dfsBack(int bx, int by); // 终点到起点后向深度搜索
bool moveFront(int fx, int fy, int i, int &nx, int &ny);// 下右移是否出界,并返回移动后的坐标
bool moveBack(int bx, int by, int i, int &nx, int &ny); // 上左移是否出界,并返回移动后的坐标
int n;
int a[11][11]; // 对数组进行周边扩充一圈0
int tmp = 0; // 一次深搜的数值大小
int ans = 0; // 各种深搜情况的最大值
int main(){
cin >> n;
memset(a, 0, sizeof(a));
int i, j, v;
cin >> i >> j >> v;
while(i != 0 || j != 0 || v || 0){
a[i][j] = v;
cin >> i >> j >> v;
}
dfsFront(0, 0);
cout << ans << endl;
return 0;
}
void dfsFront(int fx, int fy){
if(fx == n && fy == n){ // 到了终点后,进入后向深度搜索
dfsBack(fx, fy);
return;
}
int nx, ny;
for(int i = 0; i <= 1; i++){
if(moveFront(fx, fy, i, nx, ny)){
int k = a[nx][ny]; // 前向深搜到达该位置后,该位置数值变为0
a[nx][ny] = 0;
tmp += k; // 计数累计增加
dfsFront(nx, ny);
tmp -= k; // 该位置向另一方向移动时要减去向上个方向移动时累加的数值
a[nx][ny] = k; // 并复原一个方向的位置的原始值
}
}
}
void dfsBack(int bx, int by){
if(bx == 0 && by == 0){
ans = max(ans, tmp); // 一次完整深搜完成,比较得出最大的深搜结果
return;
}
int nx, ny;
for(int i = 2; i <= 3; i++){
if(moveBack(bx, by, i, nx, ny)){
tmp += a[nx][ny];
dfsBack(nx, ny);
tmp -= a[nx][ny];
}
}
}
bool moveFront(int fx, int fy, int i, int &nx, int &ny){
if(i == 0){ // 下移
nx = fx + 1; // 右移
ny = fy;
}else if(i == 1){
nx = fx;
ny = fy + 1;
}
if(nx < 0 || nx > n || ny < 0 || ny > n){ // 越界
return false;
}else{
return true;
}
}
bool moveBack(int bx, int by, int i, int &nx, int &ny){
if(i == 2){ // 上移
nx = bx - 1; // 左移
ny = by;
}else if(i == 3){
nx = bx;
ny = by - 1;
}
if(nx < 0 || nx > n || ny < 0 || ny > n){ // 越界
return false;
}else{
return true;
}
}
算法二:两次动态规划+贪心(假设第一次的动态规划解为整体最优解第一步最优解的基础上进行第二次动态规划),但是结果不完全对 。
#include<iostream>
#include<cstring>
#define MAX 15
using namespace std;
int main(){
int n;
int i, j, v;
int dp[MAX][MAX]; // 动态规划二维数组
int map[MAX][MAX]; // 记录地图
int dir[MAX][MAX]; // 记录每一步走的方向,0为上,1为左
int ans = 0; // 最终结果
memset(dp, 0, sizeof(dp)); // 矩阵初始化
memset(map, 0, sizeof(map));
cin >> n;
cin >> i >> j >> v;
while(i != 0 || j != 0 || v != 0){ // 读入数据
map[i][j] = v;
cin >> i >> j >> v;
}
for(i = 1; i <= n; i++){ // 第一次动态规划
for(j = 1; j <= n; j++){ // 状态转移方程
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) + map[i][j];
if(dp[i - 1][j] > dp[i][j - 1]){
dir[i][j] = 0;
}else{
dir[i][j] = 1;
}
}
}
i = n, j = n;
ans += dp[n][n]; // 第一次行走的最大值
while(i !=0 && j != 0){ // 倒着寻找路径,并置零
map[i][j] = 0;
if(dir[i][j] == 0){
i--;
}else{
j--;
}
}
memset(dp, 0, sizeof(dp)); // 再次初始化
for(i = 1; i <= n; i++){ // 第二次动态规划
for(j = 1; j <= n; j++){
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) + map[i][j];
}
}
ans += dp[n][n]; // 加上第二次行走的最大值
cout << ans << endl;
return 0;
}
算法三:四维数组动态规划,两个人一起走。
#include<iostream>
#include<cstring>
#define MAX 15
using namespace std;
int main(){
int map[MAX][MAX];
int dp[MAX][MAX][MAX][MAX];
memset(map, 0, sizeof(map));
memset(dp, 0, sizeof(dp));
int n;
int i, j, k, l, v;
cin >> n;
while(cin >> i >> j >> v){
if(i == 0 && j ==0 && v == 0){
break;
}else{
map[i][j] = v;
}
}
for(i = 1; i <= n; i++){
for(j = 1; j <= n; j++){
for(k = 1; k <= n; k++){
for(l = 1; l <= n; l++){
// 状态转移方程
int temp1 = max(dp[i - 1][j][k - 1][l], dp[i - 1][j][k][l - 1]);
int temp2 = max(dp[i][j - 1][k - 1][l], dp[i][j - 1][k][l - 1]);
dp[i][j][k][l] = max(temp1, temp2) + map[i][j];
// 是否在同一点
if(i != k){
dp[i][j][k][l] += map[k][l];
}
}
}
}
}
cout << dp[n][n][n][n] << endl;
return 0;
}