• 【模拟】bzoj1686: [Usaco2005 Open]Waves 波纹


    打完模拟题来庆祝一波:);感觉最近陷入一种“口胡五分钟打题两小时”的巨坑之中……

    Description

    Input

        第1行:四个用空格隔开的整数Pj Bi,B2,R. P(1≤P≤5)表示石子的个数,Bi(-5×100000≤Bi≤5×100000)和B2(-5×100000≤B2≤5×100000)表示两个河堤的z坐标,R(1≤R≤5×100000)表示你要描述湖面多少秒.没有两个石子会在同一时间砸到同一地点,两个河堤一定有不同的坐标,没有石子会砸到河堤上去.
        第2到P+1行:每行有三个用空格隔开的整数描述了一颗石子,X,K T(-5×100000≤X,K T≤5×100000).X.y表示石子砸的地点的坐标,T表示石子是什么时候砸下去的.

    Output

        输出是一个9半9的矩阵,中心在(0,0)点.左下点的坐标为(-4,-4),右上点的坐标为(4,4).这个矩阵表现的是R秒时湖面状态.

    题目分析

    有用的信息只有9x9的这一部分,所以我们来对于每一颗石子分别处理。

    如果只是手算前两三个石头,看上去好像状态是指数阶的感觉很吓人,但实际上显然状态是与$n$同阶的(为什么我第一眼没看出来呢……)。

    可以发现每一个水波到中心的曼哈顿距离相同,那么枚举水波就变得很容易了,我们来考虑如何计算反射。

    注意到反射时$y$坐标是不会改变的,那只需要考虑起点和终点的$x$坐标。

    有如下三种情况:

    1.大坝包含了两点,所以传递没有受到任何影响。

    2.大坝包住了起点,那么比较麻烦,需要考虑多次反射。

    3.大坝包住了终点,那么只用考虑一次反射。

    应该是有更优的写法的,不过分类讨论更稳(?)一些吧。

    之后嘛,注意不要打挂就好了。

      1 #include<bits/stdc++.h>
      2 
      3 struct node
      4 {
      5     int a[103][103];
      6     int *const operator[](int x)
      7     {
      8         return a[x+50];
      9     }
     10     node() {}
     11 }f;
     12 int stones,lRes,rRes,times;
     13 int s;
     14 
     15 int read()
     16 {
     17     char ch = getchar();
     18     int num = 0;
     19     bool fl = 0;
     20     for (; !isdigit(ch); ch = getchar())
     21         if (ch=='-') fl = 1;
     22     for (; isdigit(ch); ch = getchar())
     23         num = (num<<1)+(num<<3)+ch-48;
     24     if (fl) num = -num;
     25     return num;
     26 }
     27 inline bool limit(int x, int y){return x>=-4&&x<=4&&y>=-4&&y<=4;}
     28 inline bool illegal(int x)
     29 {
     30     if (x<-4) return (x<lRes&&lRes<=-4)||(x<rRes&&rRes<=-4);
     31     if (x>4) return (x>lRes&&lRes>=4)||(x>rRes&&rRes>=4);
     32     return 0;
     33 }
     34 void add(int x, int y, int c)
     35 {
     36     register int bar,cnt;
     37     if (y < -4||y > 4) return;
     38     if (s < x){
     39         if ((s<=lRes&&lRes<=x)||(s<=rRes&&rRes<=x)){
     40             if (s <= lRes){
     41                 bar = lRes, x = 2*bar-x-1;
     42             }else{
     43                 cnt = 1;
     44                 while (x <= lRes||x >= rRes)
     45                 {
     46                     if (cnt) bar = rRes;
     47                     else bar = lRes;
     48                     x = 2*bar-x, cnt = 1-cnt;
     49                     if (cnt) x++;
     50                     else x--;
     51                 }
     52             }
     53         }
     54     }
     55     if (s > x){
     56         if ((x<=lRes&&lRes<=s)||(x<=rRes&&rRes<=s)){
     57             if (s >= rRes){
     58                 bar = rRes, x = 2*bar-x+1;
     59             }else{
     60                 cnt = 1;
     61                 while (x <= lRes||x >= rRes)
     62                 {
     63                     if (cnt) bar = lRes;
     64                     else bar = rRes;
     65                     x = 2*bar-x, cnt = 1-cnt;
     66                     if (cnt) x--;
     67                     else x++;
     68                 }
     69             }
     70         }
     71     }
     72     if (limit(x, y)) f[x][y] += c;
     73 }
     74 void deal(int x, int y, int t)
     75 {
     76     if (t==0){
     77         if (limit(x, y)) f[x][y]++;
     78         return;
     79     }
     80     s = x;
     81     for (int delta=0; delta<=t; delta++)
     82     {
     83         add(x+delta, y+t-delta, 1), add(x+delta, y-t+delta, 1);
     84         add(x-delta, y+t-delta, 1), add(x-delta, y-t+delta, 1);
     85     }
     86     add(x, y+t, -1), add(x, y-t, -1);
     87     add(x+t, y, -1), add(x-t, y, -1);
     88     t -= 2;
     89     if (t==0){
     90         if (limit(x, y)) f[x][y]--;
     91         return;
     92     }else if (t < 0) return;
     93     for (int delta=0; delta<=t; delta++)
     94     {
     95         add(x+delta, y+t-delta, -1), add(x+delta, y-t+delta, -1);
     96         add(x-delta, y+t-delta, -1), add(x-delta, y-t+delta, -1);
     97     }
     98     add(x, y+t, 1), add(x, y-t, 1);
     99     add(x+t, y, 1), add(x-t, y, 1);
    100 }
    101 int main()
    102 {
    103     stones = read(), lRes = read(), rRes = read(), times = read();
    104     if (lRes > rRes) std::swap(lRes, rRes);
    105     for (int i=1; i<=stones; i++)
    106     {
    107         int x = read(), y = read(), t = read();
    108         if (t > times||illegal(x)) continue;
    109         deal(x, y, times-t);
    110     }
    111     for (int j=4; j>=-4; j--)
    112     {
    113         for (int i=-4; i<=4; i++)
    114         {
    115             if (i==lRes||i==rRes) putchar('X');
    116             else if (f[i][j] < 0) putchar('o');
    117             else if (f[i][j] > 0) putchar('*');
    118             else putchar('-');
    119         }
    120         putchar('
    ');
    121     }
    122     return 0;
    123 }

    后记

    逛了一圈发现我的代码又长又慢???

    END

  • 相关阅读:
    递归的初步应用
    最大公约数与最小公倍数(低效)
    进制转换
    凸多边形的面积问题
    单词替换
    DNA排序
    字符串排序
    倒三角形
    韩信点兵
    oracle
  • 原文地址:https://www.cnblogs.com/antiquality/p/9288881.html
Copyright © 2020-2023  润新知