【HDU 1687】Lucky Light(思维+计算几何)

传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1687

题意:有一个光源,下面有很多放置的板子,问光线被板子分割之后在地上能产生多少块亮区(看题中的图就能看懂)。

分析:这个题的做法和省选第一天的C题很像,由于是求在地面上,也就是一条直线上的亮区,我们可以求出地面上被木板遮挡形成的暗区的左坐标和右坐标,然后合并区间就可以了。而求地面上的坐标,可以用相似三角形,若光源为(sx,sy),点为(x1,y1)和(x2,y2),则地面上的坐标为:sx-(sx-s1)*sy/(sy-y1)和sx-(sx-s2)*sy/(sy-y2),需要注意的是两个坐标中较小的为左,大的为右,最好不要根据输入的x1,y1,x2,y2的大小关系去判定哪个为左哪个为右,这样很容易落下某种特殊情况,因为这个点wa了6次才ac。

代码:

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
#include<map>
#include<algorithm>
using namespace std;
struct banzi{
    double startn;
    double endn;
}A[500];
bool comp(const banzi a ,const banzi b){
    return a.startn<b.startn;
}
int main(){
    int t;
    cin >> t;
    while(t--){
        int n;
        cin >> n;
        int sx,sy;
        cin >> sx >> sy;
        for(int i=0;i<n;++i){
            int x1,y1,x2,y2;
            cin >> x1 >> y1 >> x2 >> y2;
            double dian1=(double)sx-(sx-x1)*(sy)/(double)(sy-y1);
            double dian2=(double)sx-(sx-x2)*(sy)/(double)(sy-y2);
            A[i].startn=min(dian1,dian2);
            A[i].endn=max(dian1,dian2);
        }
        int light=(n>0?2:1);
        sort(A,A+n,comp);
        double endd=A[0].endn;
        for(int i=1;i<n;++i){
            if(A[i].startn<=endd){
                endd=max(endd,A[i].endn);
            } else{
                ++light;
                endd=A[i].endn;
            }
        }
        cout << light << endl;
    }
}
时间: 2024-10-31 23:09:26

【HDU 1687】Lucky Light(思维+计算几何)的相关文章

hdu 4937 Lucky Number ( 进制转换+枚举 )

题意: 有一个数n,问有多少个进制x(基数)使得n转换为x进制后的数字中只有3.4.5.6四个数. 算法: 对于只有一位数的情况,显然3.4.5.6都应该输出-1. 如果有2位数,假设这2位中高位为a,低位为b,进制为base,则 n = a * base + b,解一元一次方程即可. 如果有3位数,假设这3为从高到低分别为a.b.c,进制为base,则 n = a * base * base + b * base + c,即一元二次方程即可. 如果位数>= 4,可以暴力枚举进制数.base>

HDU 4937 Lucky Number 搜索

题意: 给你一个数,求在多少种不同的进制下这个数每一位都是3.4.5.6中的一个. 思路: 搜索.枚举这个数在任意进制下的表示,判断是否合法.当数字只有3.4.5.6时,必定有无穷种. 因为数字太大,所以直接枚举必定会超时. 下面有两种剪枝的方法: 1. 先枚举最后一位的情况. 假设数字n在base进制下表示为 a[n]...a[0],即 n = a[0] + a[1]*base^1 + ... + a[n]*base^n. 则 n - a[0] = a[1]*base^1 + ... + a[

枚举 + 进制转换 --- hdu 4937 Lucky Number

Lucky Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 294    Accepted Submission(s): 49 Problem Description “Ladies and Gentlemen, It’s show time! ” “A thief is a creative artist who ta

HDU - 5665 Lucky (技巧)

HDU - 5665 Lucky Time Limit: 1000MS   Memory Limit: 65536KB   64bit IO Format: %I64d & %I64u Submit Status Description Chaos August likes to study the lucky numbers. For a set of numbers S,we set the minimum non-negative integer,which can't be gotten

HDU 4937 Lucky Number 乱搞 + 优化

题意:给你一个数n (1- 1e12),问你有多少种进制使得 这个数用这个进制表示只有 3 . 4 . 5. 6 这4个数 解题思路:这里本来是想要枚举的,发现数太大了,这里利用到了一中很巧妙的优化方法,将 2位 和3位转化成为 一元一次 和一元二次方程,就可以有很大的优化,然后只需要枚举到7000即可 1 // File Name: 1003.cpp 2 // Author: darkdream 3 // Created Time: 2014年08月12日 星期二 12时01分53秒 4 5

HDU 4937 Lucky Number (数学,进制转换)

题目 参考自博客:http://blog.csdn.net/a601025382s/article/details/38517783 //string &replace(iterator first0, iterator last0,const_iterator first, const_iterator last); //把[first0,last0)之间的部分替换成[first,last)之间的字符串 /* 题意: 我们将3,4,5,6认为是幸运数字.给定一个十进制数n. 现在可以讲起任意转

HDU 4937 Lucky Number(数论)

HDU 4937 Lucky Number 题目链接 题意:给定一个数字,求它再x进制下,每位进制位上都只有3,4,5,6,求这样的x有多少种,如果无限种输出-1 思路:首先3 4 5 6特判掉是无限的,很容易想到就不证明了,然后就是枚举数字的最后一位3,4,5,6,然后进制数肯定来自这个数字的因子,因为剩下的数字肯定是a1x^1 + a2x^2 + a3x^3...这样的,这样只要在因子中找进制,去判断即可.找因子的方法用先分解再dfs找,直接试除会超时 代码: #include <cstdi

HDU 4937 Lucky Number 规律题_(:зゝ∠)_

把所有合法的进制打出来会发现合法的进制都是在 n/3 n/4 n/5的边上 然后暴力边上的进制数.. #include <cstdio> #include <set> typedef long long ll; bool ok(ll x, ll y) { ll v; while (x > 0) { v = x % y; if (v != 3 && v != 4 && v != 5 && v != 6) return false;

hdu 4937 Lucky Number

虽然算法清晰的不能再清晰,但是实现总是边角料错这错那. 题目大意: 给出n,找出一些进制,使得n在该进制下仅为3,4,5,6表示 解题思路: 首先,4-10000进制直接枚举计算出每一位 此外,最多只有3位,因为10000进制以上且小于1e12,最多3位,直接枚举每一位计算进制N即可 注意:如果类似我用二分或者直接求二次根式,要开个map储存已经计算出来的N进行判重,虽然数据比较弱可以不用判.最多4^3个吧,多了可能会重. #include <cstdio> #include <cstr