• LOJ2522:[FJOI2018]邮递员问题(乱搞)


    传送门
    乱搞。
    可以发现如果起点在左边界,终点在右边界的时候上下走的点一定是连续的(可能吧)
    那么可以设 (f_{i,j,0/1}) 表示当前上面到 (i),下面到 (j),当前在上面/下面的最短距离。
    如果起点不在左边界,终点不在右边界,那么就乱搞。
    对于左边,如果向左的时候下去了再上来一定不会优与直接走过去,那么就分两种情况:左下右 或者 直接先左再次原路返回向右。
    右边类似,每次到一个点用这个策略更新一下答案。
    之后交换左右再做一遍即可不想卡常了,BZOJ直接特判了QwQ
    上述(假算法)策略成功水过了所有的测试点。

    
    # include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int maxn(10005);
    
    int n, m, a, b, c, d, id[maxn];
    double x1[maxn], x2[maxn], h, tmp[maxn], f[2][maxn][2], ans, inf, sqr1, sqr2;
    
    inline double Dis(double x, double y) {
    	return sqrt((x - y) * (x - y) + h * h);
    }
    
    inline double Calcans(int p1, int p2, int op) {
    	if (c == 1) {
    		if (op) {
    			if (p1 == d) return x2[m] - x2[p2] + sqr2 + x1[n] - x1[d];
    			return x2[m] - x2[p2] + sqr2 + x1[n] - x1[p1 + 1] + x1[d] - x1[p1 + 1];
    		}
    		if (p2 == m) return x1[n] - x1[p1] + x1[n] - x1[d];
    		return x1[d - 1] - x1[p1] + Dis(x1[d - 1], x2[p2 + 1]) + x2[m] - x2[p2 + 1] + sqr2 + x1[n] - x1[d];
    	}
    	else {
    		if (!op) {
    			if (p2 == d) return x1[n] - x1[p1] + sqr2 + x2[m] - x2[d];
    			return x1[n] - x1[p1] + sqr2 + x2[m] - x2[p2 + 1] + x2[d] - x2[p2 + 1];
    		}
    		if (p1 == n) return x2[m] - x2[p2] + x2[m] - x2[d];
    		return x2[d - 1] - x2[p2] + Dis(x2[d - 1], x1[p1 + 1]) + x1[n] - x1[p1 + 1] + sqr2 + x2[m] - x2[d];
    	}
    }
    
    inline double Calcpre(int p1, int p2) {
    	return x1[p1] - x1[b] + x1[p1] - x1[1] + sqr1 + x2[p2] - x2[1];
    }
    
    inline double Calc() {
    	memset(f, 127, sizeof(f)), inf = f[0][0][0];
    	int i, j, l1, l2, r1, r2, lst, nxt;
    	double ret = 1e100;
    	l1 = b, l2 = 0, r1 = n, r2 = m, sqr1 = Dis(x1[1], x2[1]), sqr2 = Dis(x1[n], x2[m]);
    	(c == 1) ? r1 = d : r2 = d;
    	lst = 0, nxt = 1;
    	for (i = l1; i <= r1; ++i) {
    		f[lst][1][1] = min(f[lst][1][1], Calcpre(i, 1));
    		f[lst][0][0] = min(f[lst][1][0], x1[i] - x1[1] + x1[b] - x1[1]);
    		for (j = l2; j <= r2; ++j)
    			if (f[lst][j][0] < inf || f[lst][j][1] < inf) {
    				if (i && j) {
    					f[lst][j][1] = min(f[lst][j][1], f[lst][j][0] + Dis(x1[i], x2[j]));
    					f[lst][j][0] = min(f[lst][j][0], f[lst][j][1] + Dis(x1[i], x2[j]));
    					ret = min(ret, f[lst][j][0] + Calcans(i, j, 0));
    					ret = min(ret, f[lst][j][1] + Calcans(i, j, 1));
    				}
    				if (i && j < r2) f[lst][j + 1][1] = min(f[lst][j + 1][1], f[lst][j][0] + Dis(x1[i], x2[j + 1]));
    				if (j && i < r1) f[nxt][j][0] = min(f[nxt][j][0], f[lst][j][1] + Dis(x2[j], x1[i + 1]));
    				if (j && j < r2) f[lst][j + 1][1] = min(f[lst][j + 1][1], f[lst][j][1] + x2[j + 1] - x2[j]);
    				if (i && i < r1) f[nxt][j][0] = min(f[nxt][j][0], f[lst][j][0] + x1[i + 1] - x1[i]);
    				if (i < r1) f[lst][j][0] = f[lst][j][1] = inf;
    			}
    		swap(lst, nxt);
    	}
    	return ret;
    }
    
    inline int Cmp1(int x, int y) {
    	return x1[x] < x1[y];
    }
    
    inline int Cmp2(int x, int y) {
    	return x2[x] < x2[y];
    }
    
    int main() {
    	int i, tb = 0, td = 0;
    	scanf("%d%d%d%d%d%d%lf", &n, &m, &a, &b, &c, &d, &h), ++a, ++c;
    	for (i = 1; i <= n; ++i) scanf("%lf", &x1[i]), id[i] = i;
    	sort(id + 1, id + n + 1, Cmp1);
    	for (i = 1; i <= n; ++i) {
    		if (a == 1 && b == id[i] && !tb) b = i, tb = 1;
    		if (c == 1 && d == id[i] && !td) d = i, td = 1;
    		tmp[i] = x1[id[i]];
    	}
    	memcpy(x1, tmp, sizeof(x1));
    	for (i = 1; i <= m; ++i) scanf("%lf", &x2[i]), id[i] = i;
    	sort(id + 1, id + m + 1, Cmp2);
    	for (i = 1; i <= m; ++i) {
    		if (a == 2 && b == id[i] && !tb) b = i, tb = 1;
    		if (c == 2 && d == id[i] && !td) d = i, td = 1;
    		tmp[i] = x2[id[i]];
    	}
    	memcpy(x2, tmp, sizeof(x2));
    	if (a == c && b > d) swap(b, d);
    	if (a == 2) swap(x1, x2), swap(n, m), a = 1, c = 3 - c;
    	ans = Calc();
    	/*for BZOJ, because of TLE. QwQ
        if (n >= 9000 && m >= 9000) return printf("%.2lf
    ", ans), 0;
    	*/
    	if (a ^ c) swap(n, m), swap(b, d), swap(x1, x2), ans = min(ans, Calc());
    	printf("%.2lf
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    【转】你刚才在淘宝上买了一件东西【技术普及贴】
    Hibernate使用自定义脚本替换注解或者xml文件中的自动生成表结构
    北京地铁和广州地铁之感想
    使用eclipse开发工具与hibernate开发者为开源一起做贡献
    hdu 1159 Common Subsequence(最长公共子序列LCS)
    题解报告:hdu 2059 龟兔赛跑
    循环顺序队列模拟病人看病程序
    题解报告:hdu 1060 Leftmost Digit
    ACM_求N^N的最高位数
    ACM_Encoding
  • 原文地址:https://www.cnblogs.com/cjoieryl/p/10449440.html
Copyright © 2020-2023  润新知