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;
    }
    
  • 相关阅读:
    Algebraic Data Type 及其在 Haskell 和 Scala 中的表现
    理解Rust的引用与借用
    ZooKeeper学习之路 (九)利用ZooKeeper搭建Hadoop的HA集群
    ZooKeeper学习之路 (八)ZooKeeper原理解析
    ZooKeeper学习之路 (七)ZooKeeper设计特点及典型应用场景
    ZooKeeper学习之路 (六)ZooKeeper API的简单使用(二)级联删除与创建
    ZooKeeper学习之路 (五)ZooKeeper API的简单使用 增删改查
    ZooKeeper学习之路 (四)ZooKeeper开发环境eclipse配置
    Zookeeper学习之路 (三)shell操作
    Zookeeper学习之路 (二)集群搭建
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/5814755.html
Copyright © 2011-2022 走看看