蓝桥杯真题(动态规划):修路(C/C++)题解
思路:
1.dp数组:1)上下所有点都需要经过,2)只能向右或在两路中间走,3)上n点,下m点;
结合以上可以很容想到dp[n][m],表示上经过n点,下经过m点所走的最短距离,但还有一个问题需要考虑:最后到达的点是上边的第n点还是下边的第m点(假设第n,m点距离起始点最远),终点不同总路程大概率不同,因此使用dp[n][m][0],dp[n][m][1]分别表示终点为n和终点为m点所走的路程。
2.分析状态转移方程:
dp[i][j][0]=min(dp[i-1][j][0]+w1,dp[i-1][j][1]+w2);
dp[i][j][1]=min(dp[i][j-1][0]+w2,dp[i][j-1][1]+w3);
分析:
3.注意数组边界值,数据范围,输入内容等
代码:
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
double dp[2005][2005][2];
ll a[2005],b[2005];
int n,m;
double w1,w2,w3,d;
int main()
{
cin>>n>>m>>d;
dp[0][0][0]=0,dp[0][0][1]=d;
for(int i=1;i<=n;i++)
cin>>a[i];
sort(a+1,a+n+1);
for(int i=1;i<=n;i++)
{
dp[i][0][0]=a[i];
dp[i][0][1]=a[i]+sqrt(d*d+a[i]*a[i]);
}
for(int j=1;j<=m;j++)
cin>>b[j];
sort(b+1,b+m+1);
for(int j=1;j<=m;j++)
{
dp[0][j][1]=sqrt(d*d+b[1]*b[1])-b[1]+b[j];
dp[0][j][0]=dp[0][j][1]+sqrt(d*d+b[j]*b[j]);
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
w1=a[i]-a[i-1];
w2=sqrt(abs(a[i]-b[j])*abs(a[i]-b[j])+d*d);
w3=b[j]-b[j-1];
dp[i][j][0]=min(dp[i-1][j][0]+w1,dp[i-1][j][1]+w2);
dp[i][j][1]=min(dp[i][j-1][0]+w2,dp[i][j-1][1]+w3);
}
}
printf("%.2f",min(dp[n][m][0],dp[n][m][1]));
return 0;
}