画廊【第十一届】【蓝桥杯决赛】【A组】 (2串DP问题)
思路:
- 和 2个字符串的公共子序列的最大值类似
- 按照这个思路DP即可,相当于枚举了所有情况

#include <bits/stdc++.h> using namespace std; #define ri register int #define M 510 // 24 double dp[M][M][4]; long long a[M],b[M]; long long n,m,d; double w; double get(int x,int y) { return sqrt(abs(a[x]-b[y])*abs(a[x]-b[y])+w*w); } int main(){ ios::sync_with_stdio(false); cin.tie(0); cin>>n>>m>>d>>w; for(ri i=1;i<=n;i++) cin>>a[i]; for(ri j=1;j<=m;j++) cin>>b[j]; for(ri i=0;i<=n;i++) { for(ri j=0;j<=m;j++) { dp[i][j][2]=1e9; dp[i][j][1]=1e9; } } dp[1][0][1]=sqrt(abs(a[1])*abs(a[1])+(w/2)*(w/2)); dp[0][1][2]=sqrt(abs(b[1])*abs(b[1])+(w/2)*(w/2)); for(ri i=0;i<=n;i++) { for(ri j=0;j<=m;j++) { if(i==0&&j==0) continue; if(i==0) { if(j==1) continue; dp[i][j][2]=dp[i][j-1][2]+b[j]-b[j-1]; continue; } if(j==0) { if(i==1) continue; dp[i][j][1]=dp[i-1][j][1]+a[i]-a[i-1]; continue; } dp[i][j][1]=min(dp[i-1][j][1]+a[i]-a[i-1],dp[i][j][1]); dp[i][j][1]=min(dp[i-1][j][2]+get(i,j),dp[i][j][1]); dp[i][j][2]=min(dp[i][j-1][2]+b[j]-b[j-1],dp[i][j][2]); dp[i][j][2]=min(dp[i][j-1][1]+get(i,j),dp[i][j][2]); } } double ans=min(dp[n][m][1]+sqrt(abs(d-a[n])*abs(d-a[n])+(w/2)*(w/2)),dp[n][m][2]+sqrt(abs(d-b[m])*abs(d-b[m])+(w/2)*(w/2))); cout<<fixed<<setprecision(2)<<ans; return 0; }
注意:
- 在 子部x的时候一定要看他有没有超范围,不然就G了,开longlong或者1ll,
- double 的范围特别大