两台月球矿车从A点向B点移动探测,每台矿车每次可以向右或向下移动一步,移动到的位置对应的数据为可采集的矿石数量 假设每台矿车矿石装载量无限,请求出两台矿车都到达B点后采集到的矿石数量总和最大值,并将他们经过的路径输出 动态规划问题
算法思想 代码和伪代码 复杂度(空间和时间)
可以当作一辆车,第一辆车先走,采集过的置为0,然后第2辆车再走.这种贪心策略是错误的
用两个状态数组
(这题还真不简单啊)
像这种这么难的题目,我们干脆直接写个DFS,思考正解太浪费时间,应该还能骗点分
毕竟试过了好几种二维数组可能的状态,比如f[i][j]表示从(1,1)走到(i,j)的最大值,都不行。
最终才发现这是个双线程dp,用到四维数组。
两个车车火星车一个一个走,相当于同时走,这个应该也可以理解吧(相当于巧算周长)
然后就能想到这样一个数组:
f[i][j][k][g]表示两个车车火星车分别从(1,1)走到(i,j)和(k,g),能拿到的矿石最大值。
f[i][j][k][g]的依赖项是:f[i-1][j][k][g-1],f[i-1][j][k-1][g],f[i][j-1][k][g-1],f[i][j-1][k-1][g]
操作:取最大值
注意由于是四维数组,容易爆空间,最好设置成f[129][129][129][129]比较安全。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=129;
int n,m,a[N][N],f[N][N][N][N];
int main() {
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
cin>>a[i][j];
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int k=1;k<=n;k++)
for(int g=1;g<=n;g++){
//此时,第一种走法走了i+j步,第二种k+g步
int tem=max(f[i-1][j][k][g-1],f[i-1][j][k-1][g]);
tem=max(tem,f[i][j-1][k][g-1]);
tem=max(tem,f[i][j-1][k-1][g]);
if(i==k&&j==g)f[i][j][k][g]=a[i][j]+tem;//同一个位置,不能加两次
else f[i][j][k][g]=a[i][j]+a[k][g]+tem;//不同的位置,那就都所有的拿走矿石
}
cout<<f[n][n][n][n];
return 0;
}
设地图是M
把所有能走的路径都走一遍,然后找出最大数量就行了。
这得多维数组才行啊