第一题比较简单,用exist数组判断是否在循环队列中,就可实现线性算法。

Code

 #include<iostream>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<cstdlib>
#include<fstream>
#include<sstream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<vector>
#include<stack>
using namespace std;
typedef bool boolean;
#define INF 0xfffffff
#define smin(a, b) a = min(a, b)
#define smax(a, b) a = max(a, b)
template<typename T>
inline void readInteger(T& u){
char x;
int aFlag = ;
while(!isdigit((x = getchar())) && x != '-');
if(x == '-'){
x = getchar();
aFlag = -;
}
for(u = x - ''; isdigit((x = getchar())); u = (u << ) + (u << ) + x - '');
ungetc(x, stdin);
u *= aFlag;
} int n, m;
int top;
int *s;
boolean exist[]; inline void s_push(int* sta, int x) {
exist[sta[top] + ] = false;
sta[top] = x;
exist[x + ] = true;
if(top == m - ) top = ;
else top = top + ;
} int res = ;
inline void solve() {
readInteger(m);
readInteger(n);
s = new int[(const int)(m + )];
memset(s, -, sizeof(int) * (m + ));
top = ;
for(int i = , a; i <= n; i++) {
readInteger(a);
if(!exist[a + ]) {
res++;
s_push(s, a);
}
}
printf("%d", res);
} int main() {
freopen("translate.in", "r", stdin);
freopen("translate.out", "w", stdout);
solve();
return ;
}


  因为当卡牌的选择数是固定的情况下,跳的长度也就知道了,于是就可以用四种卡牌来做状态,得到了dp方程:

  为了防止过多的无用的状态,所以就用记忆化搜索(其实直接4个for也没什么问题)

Code

 #include<iostream>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<cstdlib>
#include<fstream>
#include<sstream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<vector>
#include<stack>
using namespace std;
typedef bool boolean;
#define INF 0xfffffff
#define smin(a, b) a = min(a, b)
#define smax(a, b) a = max(a, b)
template<typename T>
inline void readInteger(T& u){
char x;
int aFlag = ;
while(!isdigit((x = getchar())) && x != '-');
if(x == '-'){
x = getchar();
aFlag = -;
}
for(u = x - ''; isdigit((x = getchar())); u = (u << ) + (u << ) + x - '');
ungetc(x, stdin);
u *= aFlag;
} int n, m;
int counter[];
int f[][][][];
boolean vis[][][][];
int *val; inline void init() {
readInteger(n);
readInteger(m);
memset(counter, , sizeof(counter));
memset(f, , sizeof(f));
memset(vis, false, sizeof(vis));
val = new int[(const int)(n + )];
for(int i = ; i <= n; i++) readInteger(val[i]);
for(int i = , a; i <= m; i++) {
readInteger(a);
counter[a - ]++;
}
f[][][][] = val[];
vis[][][][] = true;
} int dfs(int a, int b, int c, int d) {
if(vis[a][b][c][d]) return f[a][b][c][d];
vis[a][b][c][d] = true;
int pos = a * + b * + c * + d * + ;
int ra = , rb = , rc = , rd = ;
if(a > ) ra = dfs(a - , b, c, d);
if(b > ) rb = dfs(a, b - , c, d);
if(c > ) rc = dfs(a, b, c - , d);
if(d > ) rd = dfs(a, b, c, d - );
smax(f[a][b][c][d], max(ra, max(rb, max(rc, rd))) + val[pos]);
return f[a][b][c][d];
} inline void solve() {
int res = dfs(counter[], counter[], counter[], counter[]);
printf("%d", res);
} int main() {
freopen("tortoise.in", "r", stdin);
freopen("tortoise.out", "w", stdout);
init();
solve();
return ;
}


  这道题相当于是安排罪犯,使所有的影响力的最大值最小,于是就不难想到二分答案。

  对于当前二分值mid,无视所有权值小于等于它的边,判断是否能让剩下的边构成二分图。至于这一步多次对未访问的点进行dfs,将与它相连的点丢进另一个监狱,如果出现矛盾,就说明当前的二分值不合法。

Code

 #include<iostream>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<cstdlib>
#include<fstream>
#include<sstream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<vector>
#include<stack>
using namespace std;
typedef bool boolean;
#define INF 0xfffffff
#define smin(a, b) a = min(a, b)
#define smax(a, b) a = max(a, b)
template<typename T>
inline void readInteger(T& u){
char x;
int aFlag = ;
while(!isdigit((x = getchar())) && x != '-');
if(x == '-'){
x = getchar();
aFlag = -;
}
for(u = x - ''; isdigit((x = getchar())); u = (u << ) + (u << ) + x - '');
ungetc(x, stdin);
u *= aFlag;
} typedef class Edge {
public:
int end;
int next;
int w;
Edge(const int end = , const int next = , const int w = ):end(end), next(next), w(w) { }
}Edge; typedef class MapManager{
public:
int ce;
int *h;
Edge *edge;
MapManager(){}
MapManager(int points, int limit):ce(){
h = new int[(const int)(points + )];
edge = new Edge[(const int)(limit + )];
memset(h, , sizeof(int) * (points + ));
}
inline void addEdge(int from, int end, int w){
edge[++ce] = Edge(end, h[from], w);
h[from] = ce;
}
inline void addDoubleEdge(int from, int end, int w){
addEdge(from, end, w);
addEdge(end, from, w);
}
Edge& operator [](int pos) {
return edge[pos];
}
}MapManager;
#define m_begin(g, i) (g).h[(i)] int n, m;
MapManager g;
int* belong;
int maxval = -; inline void init() {
readInteger(n);
readInteger(m);
g = MapManager(n, * m);
belong = new int[(const int)(n + )];
for(int i = , a, b, w; i <= m; i++) {
readInteger(a);
readInteger(b);
readInteger(w);
g.addDoubleEdge(a, b, w);
smax(maxval, w);
}
} boolean dfs(int node, int val, int x) {
if(belong[node] != -) return belong[node] == val;
else belong[node] = val;
for(int i = m_begin(g, node); i != ; i = g[i].next) {
if(g[i].w <= x) continue;
int& e = g[i].end;
if(!dfs(e, val ^ , x)) return false;
}
return true;
} boolean check(int x) {
memset(belong, -, sizeof(int) * (n + ));
for(int i = ; i <= n; i++) {
if(belong[i] == -)
if(!dfs(i, , x)) return false;
}
return true;
} inline void solve() {
int l = , r = maxval;
while(l <= r) {
int mid = (l + r) >> ;
if(!check(mid)) l = mid + ;
else r = mid - ;
}
printf("%d", r + );
} int main() {
freopen("prison.in", "r", stdin);
freopen("prison.out", "w", stdout);
init();
solve();
return ;
}


  对于可以使干旱区的每个城市都能够获得水的情况,那么对于湖泊边的某个城市建的蓄水厂,能够提供给干旱区的城市水的集合,是一段连续的区间。这里可以简要地说明一下

  假设上面的命题不成立,就会出现形如上面的情况,那么为了使中间的小圆圈所在的城市可以得到供水,那么一定会有其他的水路和这几条水路交叉,也就是说这个蓄水厂还是可以给小圆圈所在的城市供水,矛盾,所以上面的命题成立。

  于是我们可以通过M次dfs得到假设在第一行第i个城市建蓄水厂所能够供水的区间,当然这样的时间复杂度最极端的情况下是O(m2n)。但是仔细一想,对于一个点(i,j)它可以到达的干旱区城市,那么某个可以到达它的点(i+a,j+b)一定也可以到达它所可以到达的干旱区城市,于是只需要一些dfs从没有被访问的第一行的城市开始搜索,因为每个城市只会被访问一次,所以时间复杂度为O(mn),降回了可以接受的范围。

  得到了这么一堆区间可以干什么?我们是需要选择一些区间使得它们的并集是整个干旱区,于是可以用dp[i]来表示完全覆盖干旱区第1个城市到第j个城市的最小所需的区间,于是又得到了方程:

Code

 #include<iostream>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<cstdlib>
#include<fstream>
#include<sstream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<vector>
#include<stack>
using namespace std;
typedef bool boolean;
#define INF 0xfffffff
#define smin(a, b) a = min(a, b)
#define smax(a, b) a = max(a, b)
template<typename T>
inline void readInteger(T& u){
char x;
int aFlag = ;
while(!isdigit((x = getchar())) && x != '-');
if(x == '-'){
x = getchar();
aFlag = -;
}
for(u = x - ''; isdigit((x = getchar())); u = (u << ) + (u << ) + x - '');
ungetc(x, stdin);
u *= aFlag;
} typedef class Point {
public:
int x, y;
int l, r; Point(const int x = , const int y = , const int l = , const int r = ):x(x), y(y), l(l), r(r) { } boolean mergable(Point& b) {
if(b.l < l) return true;
if(b.r > r) return true;
return false;
}
void merge(Point& b) {
smin(l, b.l);
smax(r, b.r);
}
}Point; int n, m;
int mat[][]; inline void init() {
readInteger(n);
readInteger(m);
for(int i = ; i <= n; i++) {
for(int j = ; j <= m; j++) {
readInteger(mat[i][j]);
}
}
} const int mover[][] = {{, , , -}, {, , -, }}; Point f[][];
boolean vis[][];
Point dfs(int x, int y) {
if(vis[x][y]) return f[x][y];
vis[x][y] = true;
f[x][y] = Point(x, y, , );
if(x == n) f[x][y] = Point(x, y, y, y);
for(int k = ; k < ; k++) {
int x1 = x + mover[][k], y1 = y + mover[][k];
if(x1 < || x1 > n) continue;
if(y1 < || y1 > m) continue;
if(mat[x1][y1] < mat[x][y]) {
Point e = dfs(x1, y1);
f[x][y].merge(e);
}
}
return f[x][y];
} void dfs1(int x, int y) {
if(vis[x][y]) return;
vis[x][y] = true;
for(int k = ; k < ; k++) {
int x1 = x + mover[][k], y1 = y + mover[][k];
if(x1 < || x1 > n) continue;
if(y1 < || y1 > m) continue;
if(mat[x1][y1] < mat[x][y]) {
Point e = dfs(x1, y1);
f[x][y].merge(e);
}
}
} int *dp;
inline void solve() {
memset(vis, false, sizeof(vis));
for(int i = ; i <= m; i++)
if(!vis[][i])
dfs(, i);
dp = new int[(const int)(m + )];
memset(dp, , sizeof(int) * (m + ));
for(int i = ; i <= m; i++)
if(f[][i].l < )
dp[f[][i].l] += , dp[f[][i].r + ] -= ;
int unget = ;
for(int i = ; i <= m; i++) {
if(!vis[n][i])
unget++;
}
if(unget > ) {
printf("0\n%d", unget);
return;
}
memset(dp, 0x7f, sizeof(int) * (m + ));
dp[] = ;
for(int i = ; i <= m; i++) {
for(int j = ; j <= m; j++) {
if(f[][j].l > i || f[][j].r < i) continue;
smin(dp[i], dp[f[][j].l - ] + );
}
}
printf("1\n%d", dp[m]);
} int main() {
freopen("flow.in", "r", stdin);
freopen("flow.out", "w", stdout);
init();
solve();
return ;
}

noip2010 真题练习 2017.2.18的更多相关文章

  1. noip2008 真题练习 2017.2.25

    不是有很多可以说的,记住不能边算边取min Code #include<iostream> #include<fstream> #include<sstream> ...

  2. 2015.12.21~2015.12.24真题回顾!-- HTML5学堂

    2015.12.21~2015.12.24真题回顾!-- HTML5学堂 山不在高,有仙则名!水不在深,有龙则灵!千里冰封,非一日之寒!IT之路,须厚积薄发!一日一小练,功成不是梦!小小技巧,尽在HT ...

  3. NOIP2010~2017部分真题总结

    NOIP2010~2017部分真题总结 2010 (吐槽)md这个时候的联赛还只有4题吗? 引水入城 只要发现对于有合法解的地图,每个蓄水厂贡献一段区间这个结论就很好做了 那么\(O(n^3)\)对每 ...

  4. NOIP2010提高组真题部分整理(没有关押罪犯)

    目录 \(NOIP2010\)提高组真题部分整理 \(T1\)机器翻译: 题目背景: 题目描述: 输入输出格式: 输入输出样例: 说明: 题解: 代码: \(T2\)乌龟棋 题目背景: 题目描述: 输 ...

  5. 美团点评2017校招笔试真题-算法工程师A

    美团点评2017校招笔试真题-算法工程师A 1.下面哪种STL容器的实现和其它三个不一样 A. set B. deque C. multimap D. map 正确答案: B STL的容器可以分为以下 ...

  6. 美团点评2017校招笔试真题-算法工程师B

    美团点评2017校招笔试真题-算法工程师B 1.以下关于经典的k-means聚类的说法哪个是错误的? A:k-means聚类算法是全局收敛的 B:k-means的聚类结果和初始聚类中心点的选取有关 C ...

  7. ACM-ICPC(10 / 10)——(完美世界2017秋招真题)

    今天学了莫比乌斯反演,竟然破天荒的自己推出来了一个题目!有关莫比乌斯反演的题解,和上次的01分数规划的题解明天再写吧~~~ 学长们都在刷面试题,我也去试了试,120分钟,写出6题要有一点熟练度才行.先 ...

  8. 1054. 求平均值 (20)-PAT乙级真题

    今天刚刚到学校,2017年学习正式开始了,今天看到了浙大的<数据结构>这学期又要开课了,决定一定要跟着学习一遍:在大学生mooc网上学习:http://www.icourse163.org ...

  9. 第三届蓝桥杯 c/c++真题

    第三届蓝桥杯真题 c/c++ 以下题目我自己也并不是所有的题目都是一次性就能做对或是有结题思路的.有些题目也是经过查证网上相关的资料或是参考了别人的代码和解题思路才做出来的.总的来看,这份题目考了很多 ...

随机推荐

  1. oozie学习笔记

    #################################################################################################### ...

  2. 第一个socket服务端程序

    第一个socket服务端程序 #include <stdio.h> #include <stdlib.h> #include <string.h> #include ...

  3. YYLabel计算富文本高度-膜拜大神

    http://www.jianshu.com/p/07cd655fee7e YYTextLayout *layout = [YYTextLayout layoutWithContainerSize:C ...

  4. LoadRunner-参数化(添加参数值)

    录制完脚本后,想要对脚本重复使用需要对某些值设定为参数,如accounts和password. 1.选中需要参数化的accounts值,点击右键->选择Replace with a parame ...

  5. [python+opencv] ROI(Range Of Interest)与泛洪填充

    python+opencv3.3视频教学 基础入门笔记(贾志刚老师) https://www.bilibili.com/video/av24998616/?p=8 ROI(Range Of Inter ...

  6. kubernetes实战(二十五):kubeadm 安装 高可用 k8s v1.13.x

    1.系统环境 使用kubeadm安装高可用k8s v.13.x较为简单,相比以往的版本省去了很多步骤. kubeadm安装高可用k8s v.11 和 v1.12 点我 主机信息 主机名 IP地址 说明 ...

  7. mysql获取下一篇和上一篇文章的ID

    mysql获取上一篇和下一篇文章的ID只要在当前页面读取上一个和下一个的ID就可以了.假设当前ID为10:搜索上一个的ID:select  id  from table where id<10 ...

  8. innodb next-key lock引发的死锁

    innodb的事务隔离级别是可重复读级别且innodb_locks_unsafe_for_binlog禁用,也就是说允许next-key lock CREATE TABLE `LockTest` (  ...

  9. 异常处理:No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer

    No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no pro ...

  10. Bug笔记:Google Map第一次缩放位置偏移

    这是个让人蛋疼的bug,认真查看Google maps API文档的童鞋们一定不会碰到. 我的同事为项目写了个针对map这块的jQuery plugin,然后在项目测试中发现,刚加载完页面时,直接点击 ...