• 【模拟】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

  • 相关阅读:
    在WCF中使用Flag Enumerations
    WCF开发教程资源收集
    [转]WCF 4 安全性和 WIF 简介
    Asp.Net Web API 2 官网菜鸟学习系列导航[持续更新中]
    Asp.Net Web API 2第十八课——Working with Entity Relations in OData
    Asp.Net Web API 2第十七课——Creating an OData Endpoint in ASP.NET Web API 2(OData终结点)
    Asp.Net Web API 2第十六课——Parameter Binding in ASP.NET Web API(参数绑定)
    Asp.Net Web API 2第十五课——Model Validation(模型验证)
    函数 生成器 生成器表达式
    函数的进阶
  • 原文地址:https://www.cnblogs.com/antiquality/p/9288881.html
Copyright © 2020-2023  润新知