zoukankan      html  css  js  c++  java
  • [codeforces 241]C. Mirror Box

    [codeforces 241]C. Mirror Box

    试题描述

    Mirror Box is a name of a popular game in the Iranian National Amusement Park (INAP). There is a wooden box, 105 cm long and 100cm high in this game. Some parts of the box's ceiling and floor are covered by mirrors. There are two negligibly small holes in the opposite sides of the box at heights hl and hr centimeters above the floor. The picture below shows what the box looks like.

    In the game, you will be given a laser gun to shoot once. The laser beam must enter from one hole and exit from the other one. Each mirror has a preset number vi, which shows the number of points players gain if their laser beam hits that mirror. Also — to make things even funnier — the beam must not hit any mirror more than once.

    Given the information about the box, your task is to find the maximum score a player may gain. Please note that the reflection obeys the law "the angle of incidence equals the angle of reflection".

    输入

    The first line of the input contains three space-separated integers hl, hr, n (0 < hl, hr < 100, 0 ≤ n ≤ 100) — the heights of the holes and the number of the mirrors.

    Next n lines contain the descriptions of the mirrors. The i-th line contains space-separated vi, ci, ai, bi; the integer vi (1 ≤ vi ≤ 1000) is the score for the i-th mirror; the character ci denotes i-th mirror's position — the mirror is on the ceiling if ci equals "T" and on the floor if ci equals "F"; integers ai and bi (0 ≤ ai < bi ≤ 105) represent the x-coordinates of the beginning and the end of the mirror.

    No two mirrors will share a common point. Consider that the x coordinate increases in the direction from left to right, so the border with the hole at height hl has the x coordinate equal to 0 and the border with the hole at height hr has the x coordinate equal to 105.

    输出

    The only line of output should contain a single integer — the maximum possible score a player could gain.

    输入示例

    80 72 9
    15 T 8210 15679
    10 F 11940 22399
    50 T 30600 44789
    50 F 32090 36579
    5 F 45520 48519
    120 F 49250 55229
    8 F 59700 80609
    35 T 61940 64939
    2 T 92540 97769

    输出示例

    120

    数据规模及约定

    见“输入

    题解

    因为光线不能两次触碰到同一面镜子,所以拐点不会超过 n 个,我们不妨枚举拐点个数。确定了拐点个数后,我们设 t 是一个完整斜边(从底边反射上来再触碰到顶)在底边上投影的距离,不难列出一个一元一次方程,把 t 解出来后再遍历一遍每个镜子检查答案是否合法,合法就更新最优得分。枚举拐点个数 O(n),检查合法性 O(n),总时间复杂度 O(n2).

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <stack>
    #include <vector>
    #include <queue>
    #include <cstring>
    #include <string>
    #include <map>
    #include <set>
    using namespace std;
    
    const int BufferSize = 1 << 16;
    char buffer[BufferSize], *Head, *Tail;
    inline char Getchar() {
        if(Head == Tail) {
            int l = fread(buffer, 1, BufferSize, stdin);
            Tail = (Head = buffer) + l;
        }
        return *Head++;
    }
    int read() {
        int x = 0, f = 1; char c = getchar();
        while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
        while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
        return x * f;
    }
    
    #define maxn 110
    #define len 100000
    const double eps = 1e-6;
    int h1, h2, n, cu, cd, ans;
    struct Mirror {
    	int v, l, r;
    	bool operator < (const Mirror& t) const { return l < t.l; }
    } up[maxn], down[maxn];
    
    void check(bool cur, double t, double st) {
    	bool ok = 0;
    	int lu = 1, lastu = 0, ld = 1, lastd = 0, tmp = 0;
    	for(; st - len < eps && (lu <= cu || ld <= cd);) {
    		if(cur) {
    			while(lu < cu && st - up[lu].r > eps) lu++;
    			if(st - up[lu].l < eps || st - up[lu].r > eps || lu == lastu) return ;
    			tmp += up[lu].v; lastu = lu;
    		}
    		else {
    			while(ld < cd && st - down[ld].r > eps) ld++;
    			if(st - down[ld].l < eps || st - down[ld].r > eps || ld == lastd) return ;
    			tmp += down[ld].v; lastd = ld;
    		}
    		st += t; cur ^= 1;
    	}
    	ans = max(ans, tmp);
    	return ;
    }
    
    int main() {
    	h1 = read(); h2 = read(); n = read();
    	for(int i = 1; i <= n; i++) {
    		int v = read();
    		char tp = getchar();
    		while(!isalpha(tp)) tp = getchar();
    		if(tp == 'T') up[++cu].v = v, up[cu].l = read(), up[cu].r = read();
    		if(tp == 'F') down[++cd].v = v, down[cd].l = read(), down[cd].r = read();
    	}
    	
    	sort(up + 1, up + cu + 1);
    	sort(down + 1, down + cd + 1);
    	for(int k = 0; k <= n; k++) {
    		// down 0; up 1;
    		double t;
    		if(k & 1) {
    			t = (double)len / ((double)h1 / 100.0 + (100.0 - h2) / 100.0 + k);
    			check(0, t, t * h1 / 100.0);
    			t = (double)len / ((100.0 - h1) / 100.0 + (double)h2 / 100.0 + k);
    			check(1, t, t * (100.0 - h1) / 100.0);
    		}
    		else {
    			t = (double)len / ((double)h1 / 100.0 + (double)h2 / 100.0 + k);
    			check(0, t, t * h1 / 100.0);
    			t = (double)len / ((100.0 - h1) / 100.0 + (100.0 - h2) / 100.0 + k);
    			check(1, t, t * (100.0 - h1) / 100.0);
    		}
    	}
    	
    	printf("%d
    ", ans);
    	
    	return 0;
    }
    
  • 相关阅读:
    unixLike命令拾遗
    最大连续子序列求和详解
    Linux下的tar命令
    Laravel 视图模块运行流程
    CommonJS,AMD,CMD
    将博客搬至CSDN
    java 从头开始学 第一天(基础概念)
    普元EOS开发积累第二篇(常见错误解决方法) 持续更新
    普元部署多个应用的方法(适用EOS6.5以上版本,且无需governor中添加应用)
    普元EOS开发积累第一篇(常见错误解决方法) 持续更新
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/5814755.html
Copyright © 2011-2022 走看看