NOIP复习篇———枚举
----------------------------------------------------------------------------------------------------------------
高手的切磋不在于难题,而在于SB算法....NOIP来了,决不能犯SB错误
---------------------------------------------------------------------------------------------------------------------------------------------------------
1.1 枚举算法
#define#
  对于无从下手的问题,我们往往刻画其解空间,使得这个解空间有了上限和下限,这样,我们可以枚举这个区间值,使得问题得到解答
#优点#
  写起来很容易,构思简单,答案准确
#缺点#
  时间的长够你等一辈子
#模板#
  function findans(int l,int r)  上限l,下限r
  {
      int ans;
      for(ans=l -) r)
         if (ans可行)cnt++;  找到一个答案
 }
1.1.2 例题
                                                        《打地鼠》
题目描述 Description

打地鼠是这样的一个游戏:地面上有一些地鼠洞,地鼠们会不时从洞里探出头来很短时间后又缩回洞中。玩家的目标是在地鼠伸出头时,用锤子砸其头部,砸到的地鼠越多分数也就越高。

游戏中的锤子每次只能打一只地鼠,如果多只地鼠同时探出头,玩家只能通过多次挥舞锤子的方式打掉所有的地鼠。你认为这锤子太没用了,所以你改装了锤子,增加了锤子与地面的接触面积,使其每次可以击打一片区域。如果我们把地面看做m*n的方阵,其每个元素都代表一个地鼠洞,那么锤子可以覆盖R*C区域内的所有地鼠洞。但是改装后的锤子有一个缺点:每次挥舞锤子时,对于这R*C的区域中的所有地洞,锤子会打掉恰好一只地鼠。也就是说锤子覆盖的区域中,每个地洞必须至少有1只地鼠,且如果某个地洞中地鼠的个数大于1,那么这个地洞只会有1只地鼠被打掉,因此每次挥舞锤子时,恰好有R*C只地鼠被打掉。由于锤子的内部结构过于精密,因此在游戏过程中你不能旋转锤子(即不能互换R和C)。

你可以任意更改锤子的规格(即你可以任意规定R和C的大小),但是改装锤子的工作只能在打地鼠前进行(即你不可以打掉一部分地鼠后,再改变锤子的规格)。你的任务是求出要想打掉所有的地鼠,至少需要挥舞锤子的次数。

Hint:由于你可以把锤子的大小设置为1*1,因此本题总是有解的。

输入描述 Input Description

第一行包含两个正整数m和n;

下面m行每行n个正整数描述地图,每个数字表示相应位置的地洞中地鼠的数量。

输出描述 Output Description

输出一个整数,表示最少的挥舞次数。

样例输入 Sample Input

3 3
1 2 1
2 4 2
1 2 1

样例输出 Sample Output

4

数据范围及提示 Data Size & Hint

使用2*2的锤子,分别在左上、左下、右上、右下挥舞一次。

对于30%的数据,m,n≤5;

对于60%的数据,m,n≤30;

对于100%的数据,m,n≤100,其他数据不小于0,不大于105。

#分析#
  题目的意思是要我们找出最适合的锤子的大小,使得每次打击都不会打空或者打出界且打完所有地鼠所需要的次数最小。
  我们发现,如果求打击次数,很明显就是sum/(r*c) 这里sum表示所有地鼠个数和,r和c分别表示改装后的锤子的长和宽,那么我们只需要枚举r和c即可,但是,在枚举的时候,要注意不能打空
#代码#
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <queue>
#include <list>
#include <deque>
#include <string>
using namespace std;const int MaxN=101;int g[MaxN][MaxN],allsum=0;
int n,m,r,c,ans=0x7fffffff;
int tmp[MaxN][MaxN];bool ok(){int i,j,i1,j1;for(i=1;i<=n;i++)for(j=1;j<=m;j++)tmp[i][j]=g[i][j];for(i=1;i<=n;i++)//枚举中心点 for(j=1;j<=m;j++)if(tmp[i][j]){if(i+r<=n+1 && j+c<=m+1){int delta=tmp[i][j];for(i1=0;i1<r;i1++)for(j1=0;j1<c;j1++)tmp[i+i1][j+j1]-=delta;if(tmp[i1+i][j1+j]<0)return false;}else return false;}return true;
}int main(){scanf("%d%d",&n,&m);for(r=1;r<=n;r++)for(c=1;c<=m;c++){scanf("%d",&g[r][c]);allsum+=g[r][c];}for(r=1;r<=n;r++)//枚举锤子的长宽 for(c=1;c<=m;c++){if(allsum%(r*c)==0 && allsum/(r*c)<ans && ok()==true)ans=allsum/(r*c);}cout<<ans;return 0;
}
《Jam的计数法》
题目描述 Description

Jam是个喜欢标新立异的科学怪人。他不使用阿拉伯数字计数,而是使用小写英文字母计数,他觉得这样做,会使世界更加丰富多彩。在他的计数法中,每个数字的位数都是相同的(使用相同个数的字母),英文字母按原先的顺序,排在前面的字母小于排在它后面的字母。我们把这样的“数字”称为Jam数字。在Jam数字中,每个字母互不相同,而且从左到右是严格递增的。每次,Jam还指定使用字母的范围,例如,从2到10,表示只能使用{b,c,d,e,f,g,h,i,j}这些字母。如果再规定位数为5,那么,紧接在Jam数字“bdfij”之后的数字应该是“bdghi”。(如果我们用U、V依次表示Jam数字“bdfij”与“bdghi”,则U<V< span>,且不存在Jam数字P,使U<P<V< span>)。你的任务是:对于从文件读入的一个Jam数字,按顺序输出紧接在后面的5个Jam数字,如果后面没有那么多Jam数字,那么有几个就输出几个。

输入描述 Input Description

有2行,第1行为3个正整数,用一个空格隔开:

s t w

(其中s为所使用的最小的字母的序号,t为所使用的最大的字母的序号。w为数字的位数,这3个数满足:1≤s<T< span>≤26, 2≤w≤t-s )

第2行为具有w个小写字母的字符串,为一个符合要求的Jam数字。

所给的数据都是正确的,不必验证。

输出描述 Output Description

最多为5行,为紧接在输入的Jam数字后面的5个Jam数字,如果后面没有那么多Jam数字,那么有几个就输出几个。每行只输出一个Jam数字,是由w个小写字母组成的字符串,不要有多余的空格

样例输入 Sample Input

2 10 5

bdfij

样例输出 Sample Output

bdghi

bdghj

bdgij

bdhij

befgh

#分析#

题目的大意是给出一串字符,然后求出它的后续排列当且仅当不能有字符越界
我们观察题目,发现题目就是要我们枚举一个需要改变的位置,这个位置自然就是t+96+j-w+1
然后对于后几位处理:str[k]=str[k-1]+1
不要忘记如果找不到相应位置时,则没有Jam数字了
#代码#
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <queue>
#include <list>
#include <deque>
#include <string>
using namespace std;const int MaxN=300;char str[MaxN];
int s,t,w,l;int main(){int i;cin>>s>>t>>w;scanf("%s",str);l=strlen(str)-1;for(i=1;i<=5;i++){int j=l;while(j>=0 && str[j]==t+97+j-w)j--;if(j==-1)break;str[j]++;for(int k=j+1;k<=w-1;k++)str[k]=str[k-1]+1;cout<<str<<endl;}return 0;
}

《合数和》

题目描述 Description

用户输入一个数,然后输出从1开始一直到这个数为止(包括这个数)中所有的合数的和。

输入描述 Input Description

一个整数N,0<N<=1000

输出描述 Output Description

一行,一个整数,即从1到N中所有合数的和

样例输入 Sample Input

样例一:100

样例二:9

样例输出 Sample Output

样例一:3989

样例二:27

#分析#
  题意:找出n以内的合数,并累加起来,输出【感觉比较easy...
  至于找合数,我们有2种方法:
  1)从1~n枚举,对于每一个数用根号n的时间复杂度判断是否为合数,时间复杂度O(nlogn),有可能会TLE,我们还有更好的方法:
  2)先用O(n)的筛法筛除n以内的质数,剩余的就是合数,然后累加,时间复杂度O(2n)
#代码#
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <queue>
#include <list>
#include <deque>
#include <string>
using namespace std;const int MaxN=1001;int p[MaxN],sum,n;int getans(){int i,j;memset(p,1,sizeof(p));for(i=2;i<=n;i++)if(p[i])for(j=i*i;j<=n;j+=i)p[j]=0;for(i=2;i<=n;i++)if(!p[i])sum+=i;return sum;
}int main(){scanf("%d",&n);cout<<getans();return 0;
}

1.3 枚举算法的反思

  只有不断反思才能得到进步,枚举算法着实好,可惜,时间复杂度过于高,但我们可以优化,不过说实在的,枚举的优化也确实多。
  优化1:二分答案
   对于某些题目,它的答案是具有单调性的,所以可以用类似二分查找的方式查找答案,再判断是否可行,时间复杂度从O(N)降至O(logN),详情参考《奇怪的函数》
  优化2:离散化
   对于不必要枚举的状态或者解空间,我们可以不必算它,所以在一些题目中,可以离散掉不需要的内容,然后剩下的再进行枚举,详情参考《最佳室温》和《海报》
  优化3:搜索
   搜索也是对解空间的刻画,只不过将解空间用解空间树联系起来,然后得到解的有序性,去除了一些不必要的状态,但是,往往也是会TLE的,搜索同样也有优化,这在后面的搜索复习中会提到(形如:记忆化搜索,BFS,DFS,PFS)
  优化4:动态规划
   对于解空间的处理,我们得到小问题,再不断将小问题合并,得出原问题的解,这是动态规划的长处,空间换时间
以得到问题的求解
  优化5:数据结构
   对于查找类的题目,没有必要去一一枚举,转换,只需要用数据结构来优化浪费的查找过程即可,主要体现在堆上面,详情参考《dijkstra算法》《prim算法》《合并果子》
----------------------------------------------------------------------------------------------------------------------------------------------------

NOIP复习篇———枚举相关推荐

  1. NOIP复习篇———动态规划

    NOIP复习篇---动态规划 ------------------------------------------------------------------------------------- ...

  2. NOIP复习篇———贪心

    NOIP复习篇---贪心 --------------------------------------------------------------------------------------- ...

  3. C语言复习篇之数组与指针

    C语言复习篇之数组与指针 学习了一段时间的嵌入式linux了,学习中有很多的东西需要总结,有经验有教训,我觉得把他写下来会更好,就当做是一种笔记的形式,记录学习中的点点滴滴,不仅仅自己可以经常复习,也 ...

  4. 用不同的姿势求逆序对(复习篇)

    用不同的姿势求逆序对(复习篇) 文章目录 用不同的姿势求逆序对(复习篇) 前言 讲解 归并排序 树状数组 线段树 题目 思路 代码 归并排序求逆序对 树状数组求逆序对 线段树求逆序对 历届试题 小朋友 ...

  5. 最小生成树,回忆复习篇。

    最小生成树,回忆复习篇. 以前听过一遍最小生成树,可惜,当时没弄会.过了几天就全忘了.而如今在做LCA的时候,woc我居然不会最小生成树了. 所以来回忆一下最小生成树. kruskal算法.这个算法的 ...

  6. Android期末复习篇_传智课后习题以及答案(选择、填空、判断、简答、编码题)

    写在前面 此为移动应用开发传智课后习题及答案,供期末复习使用,注意 答案仅供参考 加粗题目为强调 题型涉及:选择.判断.填空.简答.编程题 另8章习题及答案汇总:Android期末复习篇_8章节练习题 ...

  7. 扩展欧几里得复习篇。

    扩展欧几里得复习篇. 由于多校考了欧几里得,所以这里复习一波扩欧. 这里主要讲解利用扩欧求解二元一次方程的整数解问题. 0.求解: a x + b y = g c d ( a , b ) ax+by= ...

  8. 冲刺NOIP复习,算法知识点总结

    前言        离NOIP还有一个星期,匆忙的把整理的算法补充完善,看着当时的整理觉得那时还年少.第二页贴了几张从贴吧里找来的图片,看着就很热血的.当年来学这个竞赛就是为了兴趣,感受计算机之美的. ...

  9. 2019秋招备战复习篇

    @TOC## ? 目录 ➕ C/C++ ⭐️ Effective ? STL 〽️ 数据结构 ⚡️ 算法 ❓ Problems ? 操作系统 ☁️ 计算机网络 ? 网络编程 ? 数据库 ? 设计模式 ...

最新文章

  1. Linuxshell之结构化命令
  2. JDBC+Servlet+JSP整合开发之22.JSP简介
  3. ubuntu下python thrift安装
  4. 十问十答 GPL 许可证
  5. webService发布在IIS服务器上
  6. 1. MFC编程——变量命名规则
  7. android os 2.2刷机包,N1内置CoreELEC9.2.2、安卓7.1.2双系统刷机包,全功能刷机包V2.2...
  8. calendar控件使用 extjs_Calendar 日历控件使用
  9. [转帖]方正数码发布基于龙芯3A3000系列整机
  10. mysql 分组查询 语句_MySQL分组查询
  11. Mr.张小白(案例:基于Spring MVC实现后台登陆系统验证)
  12. mysql constant number,Mysql报Too many connections,不要乱用ulimit了,看看如何正确修改进程的最大文件数...
  13. 今日头条面试——测试工程师
  14. 微信公众号如何分享课件PPT?
  15. Leap Motion 之Unity 开发实战(一. 制作手的HandController)
  16. 跨境电商淘宝详情解决方案
  17. Matlab/simulink通信系统仿真入门操作
  18. 报表可视化源码,操作界面可视化,通过简易配置即可自动生成各种类型的报表,为企业节省大量的重复开发工作
  19. python+opencv-03 高斯模糊
  20. java文件用editplus乱码,EditPlus中文乱码问题

热门文章

  1. opencv级联分类器(linux系统)
  2. plot画图 python 双线_Python使用多种滤波器对脑电数据去除伪影
  3. jenkins使用python脚本发送企业微信通知
  4. Performing Basic Amazon S3 Bucket Operations
  5. 分面导航的详细操作方案
  6. 网联车辆队列生态式协同自适应巡航控制策略研究-杨昱
  7. WebServer应用示例2:Siri语音识别读取传感器数据 | ESP32轻松学(Arduino版)
  8. 我如愿以尝被北交计算机学院录取
  9. ENSP里的路由器与本地网络互联
  10. 我刚刚做了一个艰难的决定