题目描述
小蓝办了一个画展,在一个画廊左右两边陈列了他自己的作品。为了使画展更有意思,小蓝没有等距陈列自己的作品,而是按照更有艺术感的方式陈列。
在画廊的左边陈列了 L 幅作品,在画廊的右边陈列了 R 幅作品,左边的作品距离画廊的起点依次为 u_1, u_2, · · · , u_L,右边的作品距离画廊起点依次为 v_1, v_2, · · · ,v_R。
每周,小蓝要整理一遍自己的每一幅作品。整理一幅作品的时间是固定的,但是要带着沉重的工具。从一幅作品到另一幅作品之间的距离为直线段的长度。
小蓝从画廊的起点的正中央(左右两边的中点)出发,整理好每一幅画,最终到达画廊的终点的正中央。已知画廊的宽为 w。
请问小蓝最少带着工具走多长的距离?
输入描述
输入的第一行包含四个整数 L,R,d,w,表示画廊左边和右边的作品数量,以及画廊的长度和宽度。
第二行包含 L 个正整数 u_1, u_2, · · · , u_L,表示画廊左边的作品的位置。
第三行包含 R 个正整数 v_1, v_2, · · · , v_R,表示画廊右边的作品的位置。
其中有 ,1 ≤ L, R ≤ 500, 1 ≤ d ≤ 10^5, 1 ≤ w ≤ 10^5,0 ≤ u_1 < u_2 < · · · < u_L ≤ d, 0 ≤ v_1 < v_2 < · · · < v_R ≤ d
输出描述
输出一个实数,四舍五入保留两位小数,表示小蓝最少带着工具走的距离。
输入输出样例
示例
输入
3 3 10 2
1 3 8
2 4 6
输出
14.71
本题思路
本题又是一个dp的题目(我真的会谢,写了好几道都是dp,dp我做不到啊呜呜呜)
本题的思路其实就是定义一个三维的数组,记录状态
dp[i][j]表示处理完左边第1幅画和右边第j幅画所走的最小路程,但是我们无法知道现在到底是在是在左边还是在右边,所以我们还需要增加一维数组代表现在现在到达的是左边还是右边,用0表示在左边,用1表示在右边,这样就可以确定状态
状态转移方程,假设我们现在需要到达左边那么现在有两种方法到达
一种是前一个状态在左边,另一种是前一个状态在右边
那么我们就可以写出状态转移方程
dp[i][j][0]=Math.min(dp[i][j][0],Math.min(dp[i-1][j][0]+left[i]-left[i-1], dp[i-1][j][1]+js(left[i],right[j],l)));
为何是i-1而不能是j-1的原因是因为,0表示现在到达点是i也就是说在之前状态i还没有到达,所以用i-1,而不是j-1
到达点在右边同理可以写出状态转移方程
下面上代码
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.Arrays;
public class Main画廊 {
public static void main(String[] args) throws IOException {
StreamTokenizer x=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
PrintWriter out=new PrintWriter(System.out);
x.nextToken();
int n=(int)x.nval;
x.nextToken();
int m=(int)x.nval;
x.nextToken();
int k=(int)x.nval;
x.nextToken();
int l=(int)x.nval;
int INF = 0x3f3f3f3f;
int left[]=new int[n+1];
int right[]=new int[m+1];
for(int i=1;i<=n;i++) {
x.nextToken();
left[i]=(int)x.nval;
}
for(int i=1;i<=m;i++) {
x.nextToken();
right[i]=(int)x.nval;
}
double dp[][][]=new double[n+1][m+1][2];
double pd=(double)l/2;
double a=js(0,left[1],pd);
double b=js(0,right[1],pd);
for(int i=0;i<=n;i++)//初始化,全部置为最大
for(int j=0;j<=m;j++)
Arrays.fill(dp[i][j], INF);
dp[1][0][0]=a;
dp[0][1][1]=b;
/*for(int i=1;i<=n;i++) {
dp[i][0][0]=a+left[i]-left[1];
dp[i][0][1]=INF;
}
for(int i=1;i<=m;i++) {
dp[0][i][0]=INF;
dp[0][i][1]=b+right[i]-right[1];
}*/
for(int i=0;i<=n;i++) {
for(int j=0;j<=m;j++) {
if(i!=0)dp[i][j][0]=Math.min(dp[i][j][0],Math.min(dp[i-1][j][0]+left[i]-left[i-1], dp[i-1][j][1]+js(left[i],right[j],l)));
if(j!=0)dp[i][j][1]=Math.min(dp[i][j][1],Math.min(dp[i][j-1][0]+js(left[i],right[j],l), dp[i][j-1][1]+right[j]-right[j-1]));
}
}
out.printf("%.2f\n", Math.min(dp[n][m][0]+js(k,left[n],pd), dp[n][m][1]+js(k,right[m],pd)));//最后还要到达画廊中间别忘了
out.flush();
}
public static double js(double a,double b,double h) {
a=Math.abs(a-b);
return Math.sqrt(a*a+h*h);
}
}