DAY 1
基础算法
1.模拟算法
很水,没错
关键:将人类语言翻译成机器语言
更准确的说,就是:将一个用日常大白话语言的东西用计算机语言抽象地表达出来
所以要掌握模拟算法,你要做到以下两点:
(1)优秀的读题能力
(2)优秀的代码能力
模拟算法经常出现在NOIP的赛场上,此类题目的关键点也就是上述两点:读题,写题
just like this :
此时拿到题我们不能先是写个快读压压惊,而是要站在一个High Level的角度,建模
input while { 环上行走 } output
先读题,建模,明白难点在哪里
P1563 玩具谜题
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<string> #include<cstring> #include<cstdlib> #include<queue> using namespace std; inline int read() { int ans=0; char last=' ',ch=getchar(); while(ch<'0'||ch>'9') last=ch,ch=getchar(); while(ch>='0'&&ch<='9') ans=ans*10+ch-'0',ch=getchar(); if(last=='-') ans=-ans; return ans; } int n,m,now; struct node { int bian; int num; string s; }peo[100010]; int main() { n=read();m=read(); for(int i=0;i<n;i++) { peo[i].bian =i; peo[i].num =read(); cin>>peo[i].s ; } int opr,shu,now=0; for(int i=1;i<=m;i++) { opr=read();shu=read(); if(peo[now].num ==0) { if(opr==0) now=(now-(shu%n)+n)%n; if(opr==1) now=(now+(shu%n))%n; continue; } if(peo[now].num ==1) { if(opr==1) now=(now-(shu%n)+n)%n; if(opr==0) now=(now+(shu%n))%n; } } cout<<peo[now].s <<endl; return 0; }
then:一个hin恶心的斗地主
看到这样的题hin烦啊,怎么办呢?
把问题抽象成通用模型:
手里有n张牌
有k个规则
每个规则(K<?)可以打出一定的p
请问要打完最少打多少次牌?
void dfs(剩下多少张没打last,打了多少张ans) { if(last==0) else { 处理 } }
<1>写长代码不出错的能力 ----->要有一个良好的代码习惯
<2>多方面周全的考虑问题的能力 ----->在做题时头脑中要有清晰的逻辑
一个笑话压压惊
所以写长代码的要领在于一遍写对!!!
(1)模块化结构(如何去思考一个问题)
(2)写代码前要有一个清晰的思路,建模,然后去写细节
没想清楚就不动笔,画程序逻辑图,大概就是把代码分成几部分,相当于列提纲,没必要很蠢的真的画图
(3)写完一部分就检查一部分,不然后面会有很多错误调不过来
(4)写代码,变量要有意义,特别是搜索,模拟,代码较长,不然变量a~z用下来会乱
常用循环变量x,y,z,i,j尽量不要开数组名
(5)日常模拟NOIP:
A题不要多次WA然后改然后A,
做题就考虑能不能一遍A,不能A的话,仔细检查自己造数据(对拍)
暴力代码和100?代码一起测
Rand 小数据 ,自己大数据测100?代码
尽量控制WA的概率
(6)推荐练练模拟
DAY1,2模拟题满分,后面全暴力(此乃暴力出奇迹)
(分治 if(n<10) 跑暴力 Else 跑标算)
2.贪心
贪心算法 (这个是之前整理的非常典型的典型题)
贪心题目大赏 (这个是QBZT的听课记录)
3.分治
分治算法
做题的时候:30->50->70->100
深搜剪枝代码要清晰
能写循环就不DFS
DFS-->网络爬虫
深搜记录根到当前节点的路径
BFS记录一层东西
深搜搜解
广搜搜到底
最短路,BFS吊打DFS,DFS搜完前面全搜完才会回来
数组越界hin阔怕
访问c[105]可能会跑到a里找个东西改改
起点终点交替搜,去掉了一些不合法的情况
定义了最多搜几层
要靠脑洞和缘分了
剪枝大例题