0
点赞
收藏
分享

微信扫一扫

画廊【第十一届】【决赛】

十日十月Freddie 2022-05-01 阅读 83

题目描述
小蓝办了一个画展,在一个画廊左右两边陈列了他自己的作品。为了使画展更有意思,小蓝没有等距陈列自己的作品,而是按照更有艺术感的方式陈列。

在画廊的左边陈列了 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);
	}
}
举报

相关推荐

0 条评论