zoukankan      html  css  js  c++  java
  • 总结(20170218~20170310)

      本文笔者完成于2017年3月份,当时水平有限,可能也有颇多疏漏,若有问题尽请指出,本人一定更正。


       近来,考了几套NOIP真题,另外伟大的斯堪福·胡也给考了几道,余以为甚为有趣。之前已经写了一些总结,但总还认为不够。

    20170218

    NOIP2010

    Translate

    100

    Tortoise

    0

    Prison

    0

    Flow

    30

    20170224

    两道DP

    Salesman

    100

    Power

    50

     

     

    20170225

    NOIP2009

    Word

    100

    Matches

    100

    Message

    100

    Twostack

    30

    20170303

    NOIP2005的一半

    River

    10

    Fire

    80

     

     

    20170304

    NOIP2008

    Spy

    100

    Son

    0

    Trade

    0

    Sudoku

    5

    20170310

    NOIP2011D1

    Carpet

    100

    Hotel

    10

    Mayan

    10

     

    ##**20170218 NOIP2010**

      话说这套题,第一遍做得很不好,只有130。所以说,圣人云,不以物喜,不以己悲。把握好状态,才能稳健地走下去。

      Translate这道题,不过是循环队列+模拟。但要注意,题干中是查询有没有,若没有,就计数填入。填入是先填满,填满了再先进先出。有一些同志没有意识到填入的可能是0(非负数),容易与空位混淆,从而出现错误。

      Tortoise这道题,是一道**典型**的DP题。因为只有四种牌,每种牌的数目都已给出,且用完就刚好到终点。于是可以使用四维DP,每种牌不超过40,而40^4=2560000是一个游刃有余的数。

    注意,所谓典型,是因为我们可以清晰的找出无后效性与各种状态,一点是很有必要的。

      Prison是一道很优秀的图论入门题目,可以用多种角度思考。

      **法1**:二分答案+二分图染色**O(nlogn)**

      注意到题目要求将犯人关进2个监狱,使最大仇恨值最小。于是我们可以二分答案出满足条件的最大仇恨值,每一次二分,图中只剩下边权大于等于最大仇恨值的边。而我们所要做的事,即是DFS二分图染色加以判断,最后出最优解。

      **法2**:排序+并查集**O(nlogn+n)**

      注意到题目要求将犯人关进2个监狱,使最大仇恨值最小。请想象,面对一堆犯人,我们肯定会先拆开仇恨值最大的一对,并在此基础上继续拆下去,知道我们无能为力,那这就是答案。我们可以使用并查集,同组者很好处理,但我们会刻意拆开,怎么记录呢?我们可以使用“反人”(k的反人是n+k)。

      但是,条件是乱的,所以需要排序。复杂度与法1相当,但代码短多了。而且,如果条件有序,就真的是**O(n)**的了。

      Flow引水入城大概是我目前遇过的(笔者在当时的水平有限)最好的综合题,可以DFS判断是否可以并将其化为区间覆盖问题,再DP求解。

      注意到,最后得到的结果一定是连续区间覆盖。

    ##**20170224 两道DP**

      Salesman是当时学状压DP的例题TSP问题,相当于复习。状压对时间的节省是非凡的,但占空之大(2^21=2097152)是很吓人的。一道真正的状压是藏不住的,因为数据范围太小了。

      不过,据说有一种叫做退火的神奇算法……

      power是当时学简单DP的例题,但当时是**O(n^3)**,明显会爆。我们需要用**O(n^2)**的复杂度,但怎么办呢?鉴于题目的性质,人是如洋葱般一层层的往外走,固必为连续区间,此时我们可以考虑区间DP。

      但是我们在实现时,发现二维DP不够,还需半维,因为一个区间会有两个端点,最后也有可能分别停在两个末端点。

    ##**20170225 NOIP2009**

      Word模拟,找字符串中字母出现的最高频率与最低频率(注意处理0),作差判断质数(注意0不是质数)。

      matches记忆化搜索(因n<=24不可能凑出四位数加法)或打表(n<=24,但事实证明根本不需要)。

      Message是方格取数的姊妹版,但需要注意不能重复经过同一个点。但幸好,好感度不为负,重复经过同一个点必非最优,从而让我这个逻辑不严密的家伙逃过一劫。但怎么避免重复经过同一个点呢?方案如下:

      先memset( dp, -127, sizeof( dp ) );再循环,确保所更新状态的两个点满足i != x && j != y,同时不从重复的点过来。

      但注意到,此题用四维太不优,因为我们会强制两条路同步往下走(i+j=x+y),于是可以由i,j,x推及y,从而省去一维。

      Twostack双栈排序,运用到了一个很重要的栈的性质:单调性。

      再进一步,于是便有结论1:若i<j<k,而aa[k]<aa[i]<aa[j],则i、j不可同栈;

      再进一步,于是便有结论2:若i<j,而min(aa[j+1]~aa[n])<aa[i]<aa[j], 则i、j不可同栈(DP思想);

      验证结论1,是**O(n^3)**;而验证结论2,是**O(n^2)**。

      f[n+1] = OO;

      for( int i = n; i >= 1; i-- )

        f[i] = min(f[i+1],aa[i]);

      for( int i = 1; i < n; i++ )

        for( int j = i + 1; j <= n; j++ )

          if( aa[i] < aa[j] && f[j+1] < aa[i] )//出现逆序不可处于同栈

            insert( i, j ),insert( j, i );//注意双向建边

      在此基础上,建出矛盾图,再从1开始,二分图染色(**好像prison**),注意优先放栈A。最终,模拟一遍即可。

    ##**20170303 NOIP2005的一半**

      2005年的题,话说是很有趣的。

      River是一道用数据范围卡智商的典型DP题。因为它的数据与题目描述跟NOIP 2015 T2 D1 stone颇为相似,让许多少年都想到去用二分答案,从而误入歧途。

      而我呢,听了lmy、wyy的“一面之词”,竟以为可以直接用贪心,从而只得了10分(其实对贪心已经够了)。但是,说River用数据范围卡智商,该怎么办呢?

      考虑到题目性质,L很远(1 <= L <= 10^9),但石子总数很少(1 <= M <= 100),而每跳一步限制了[S,T](1 <= S <= T <= 10)的范围,所以说任意两石子间可以缩短到至多2*t(其余的直接大跳毫无影响)。

    1 if( aa[i] - aa[i-1] > t )
    2    dis[i] = dis[i-1] + ( aa[i] - aa[i-1] ) % t + t;
    3 else dis[i] = dis[i-1] + aa[i] - aa[i-1];

      通过此方法,L可以压至最多M*2*T<=2000,这就毫无压力了,成为了一道弱智的DP题。所以,**模型的转换和技巧是很重要的**,看似很辽阔的距离,可以霎时化作咫尺,但一定要理清思路。

      Fire此题更有趣,先造环,再用两个环判断最大居原位者,但判断是否成环也颇有技巧。而我在造环是所犯的看似极小却致命的错误,居然让我得了80分,让我不禁怀疑数据……

    ##**20170304 NOIP2008**

      Spy这道题当时打着真心够呛(因为斯堪福大人叫我们手打数据……)。题目很简单,但要注意映射中对不可行的判断,这意味着你是否读懂了题。**所以,审题很重要。**

      Son是一道数论题,找满足要求的x的个数(lcm(x,a0)=b0,gcd(x,a1)=b1)。分解质因数就够了。但当时思路未通透,所以WA完了。**所以,审题很重要。**

      Trade有多种方法,是一道经典的“图上DP”(lmy如是说)。

      **法1:O(n)**该题是要选择一条道路(从1到n),低入高出求最大价格差。该题有单向边也有双向边,且可重复经过同一个点。所以,需要进行一定处理。

      我们可以先使用tarjan缩一下点,再DFS一遍,注意最值取强连通分量的。

      **但不知为何,本人至今用这个方法都只有70……**

      **法2:O(kE)**该题既然是找路径最值,低入高出,便可以使用SPFA。从1开始正着搜(正图)处理最小值,再从n开始倒着搜(反图)处理最大值。

      **但是lmy有言,我可以卡SPFA……**

      Soduku是一道很有价值的暴力题,很考耐心的。为了优化,可以使用二进制位运算(**O(1)判断某位置可填的数**)。

    ##**20170310 NOIP2011D1**

      Carpet正着读反着判简单模拟题。

      Hotel有n种方法。

      **法1:**张杰尘式DP,思路较含混但也有一定巧妙之处。**O(n)**

      **法2:**王驭洋式DP,复杂度较高且是二维的但不会超时。**O(nk)**

      **法3:**线段树区间查询,因为不用写modify所以还是比较简洁。**O(n^2+优化)**

      注意:法2完全可以用前缀和代替。

      **法4:**我的DP。直接上代码。**O(n)**

     1 readin(n);readin(k);readin(p);
     2 for( int i = 1; i <= n; i++ ) {
     3  readin(color);readin(price);
     4     if( ntot[color] < tot || price <= p ) { //pre[color]与now[color]互化
     5         pre[color] += now[color];
     6         now[color] = 0;
     7         ntot[color] = tot;
     8     }
     9     now[color]++; // pre[color]与now[color]之和是每次+1的
    10     ans += pre[color]; //pre[color],当前客栈之前可以进行配对的个数
    11     if( price <= p ) tot++;
    12 }
    13 printf( "%d
    ", ans );

      看起来还是很简洁的,个人以为思路也比较清晰。只是考试时忘了加上“|| price <= p”这一段,直接丢去90分。原则上,这是对前缀和的极度优化。

      用pre[color]来表示当前客栈之前可以进行配对的个数,now[color]来表示当前客栈之前不能进行配对的个数。可以确定的是,pre[color]与now[color]之和是每次+1的,但他们之间存在着互化的关系。这是很有趣的,也需要把思路弄清楚。

      **而我呢,就是没有过多审题,心中一片杂乱。**

      **法5:** 李明洋式DP,找全集与补集。若无最低消费限度,应当是全集。但中间有一些会失效,即是找补集。全集-补集=答案**O(n)**

     1 readin(n),readin(k),readin(p);
     2 for(register int i=1;i<=n;i++){
     3     readin(col[i]),readin(tmp);
     4     if(tmp>p)flag[i]=1;
     5 }
     6 for(register int i=1;i<=n;i++){
     7     if(flag[i]==0){
     8         memset(cnt,0,sizeof(cnt));    
     9         continue;
    10 
    11     }
    12     cnt[col[i]]++;
    13     _count+=(cnt[col[i]]-1);
    14 }
    15 memset(cnt,0,sizeof(cnt));
    16 for(register int i=1;i<=n;i++){
    17     cnt[col[i]]++;
    18     sum+=(cnt[col[i]]-1);
    19 }
    20 cout<<sum-_count<<endl;

      全集、补集的找法都是相似的,但所对应区间不同,补集对应的是一段连续都超过最低消费的区间(一定在此之内,因为外面的点是可以与里面的点对应的)。

      **register int似乎并无大用。 **

      而Mayan一如既往,仍然是一道模拟搜索暴力题,是很考耐心的。我们首先可以创建一个class类,简明的实现游戏的功能(这就成功了一大半),然后再在外面套上搜索。十分美观,且可以自己改成真正的游戏。

  • 相关阅读:
    vue store获取值时 Computed property "activeTag" was assigned to but it has no setter.
    深拷贝实现方法以及问题
    mac 中git操作账号的保存与删除
    解决Ubuntu编译内核uImage出现问题“mkimage” command not found
    ubuntu修改主机名后无法解析主机
    多行宏定义中的注释问题
    uboot启动阶段修改启动参数方法及分析
    ubuntu nfs服务器配置
    mount/umount命令详解
    Ubuntu下vsftp安装和配置
  • 原文地址:https://www.cnblogs.com/Doggu/p/test20170218.html
Copyright © 2011-2022 走看看