画廊【第十一届】【蓝桥杯决赛】【A组】 (2串DP问题)

题目: “蓝桥杯”练习系统 (lanqiao.cn)

思路:

  • 和 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;
    
} 
View Code

注意:

  • 在 子部x的时候一定要看他有没有超范围,不然就G了,开longlong或者1ll,
  • double 的范围特别大
posted @ 2022-06-14 19:08  VxiaohuanV  阅读(42)  评论(0编辑  收藏  举报