zoukankan      html  css  js  c++  java
  • 2018雅礼集训 DAY1T2 折射

    自闭了,题解都看不懂。

    Desprition

    小 Y 十分喜爱光学相关的问题, 一天他正在研究折射. 他在平面上放置了 (n) 个折射装置, 希望利用这些装置画出美丽的折线

    折线将从某个装置出发, 并且在经过一处装置时可以转向, 若经过的装置坐标依次为 ((x1, y1),(x2, y2)) . . .((xk, yk)),

    则必须满足:

    (∀) $j in (1, k], y_{j-1} < y_j $

    (∀) (j in (2 ,k]), (x_{j- 2} < x_j < x_{j_1}) (or) $ x_{j-1} < x_j < x_{j-2}$

    现在他希望你能告诉他, 一共有多少种不同的光线能被他画出来, 两种光线不同当且仅当经过的折射装置的集合不同

    . 你只需要告诉他答案对 (10^9 +7) 取模后的结果

    .Input Format

    第一行一个正整数 (n) , 表示折射装置的数量 接下来 (n) 行, 每行两个整数 (x_i , y_i) 表示折射装置的坐标

    Output Format

    输出一行一个整数, 表示答案对 (10^9 +7) 取模后的结果

    .Constraints

    对于 10% 的数据: (n≤ 700, 1 ≤ x_i, y_i≤N)

    对于 20% 的数据: (n≤ 1000, 1 ≤x_i, y_i≤N)

    对于 50% 的数据: (n≤ 4000,|x_i|,|y_i | ≤ 10^9)

    对于 100% 的数据: (n ≤ 6000,|x_i|,|y_i| ≤ 10^9)

    sloution

    自闭了,考试的时候连 (O(n^2)) 的暴力都不会,直接粘题解吧

    (dp[i][0/1]) 表示按 (x) 排序,以 (i) 为入射点的光线,向左下方 0/右下方1入射,注意这里前 (i) 并不是状态,因为

    后面可以更改这个 (dp_i) 状态。按 (x) 排序只是方便处理。

    转移:

    (∀) (y_j < y_i, dp[i][0] <- dp[j][1])

    (∀) (y_j > y_i) ,(dp[j][1] <- dp[k][0]) (y_k < y_j and x_k > x_j)

    搬运完成

    不知道为什么把 (f[i][0],f[i][1]) 初始化放在外面就不对。

    Code

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N = 6010;
    const int p = 1e9+7;
    int n,ans,f[N][2];
    struct node
    {
    	int x,y;
    }e[N];
    inline int read()
    {
        int s = 0,w = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
        while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0'; ch = getchar();}
        return s * w;
    }
    bool cmp(node a,node b)
    {
    	return a.x < b.x;
    }
    int main()
    {
    	freopen("refract.in","r",stdin);
    	freopen("refract.out","w",stdout);
        n = read();
        for(int i = 1; i <= n; i++)
        {
            e[i].x = read();
            e[i].y = read();
        }
        sort(e+1,e+n+1,cmp);
        f[1][0] = f[1][1] = 1;
        for(int i = 2; i <= n; i++)
        {
        	f[i][0] = f[i][1] = 1;
            for(int j = i-1; j; j--)
            {
                if(e[j].y > e[i].y) f[j][1] += f[i][0], f[j][1] %= p;
                if(e[j].y < e[i].y) f[i][0] += f[j][1], f[i][0] %= p;
            }
        }
        for(int i = 1; i <= n; i++) ans = (1LL * ans + f[i][0] + f[i][1]) % p;
        printf("%d
    ",(ans - n + p) % p);
        fclose(stdin); fclose(stdout);
        return 0;
    }
    
  • 相关阅读:
    小球掉落
    String当中与转换相关常用的方法有
    字符串的截取方法
    golang 管道
    golang--协程之间通信的方式
    golang--goroutine
    go 时间操作
    吉格勒定理
    检视阅读
    git branch -a发现分支显示不全
  • 原文地址:https://www.cnblogs.com/genshy/p/13877214.html
Copyright © 2011-2022 走看看