第一题比较简单,用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. The "get" method should be used when the form is idempotent---正交的两个概念 get 幂等

    https://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13.1 17.13.1 Form submission method The me ...

  2. snowflake and uuid

    分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的. 有些时候我们希望能使用一种简单一 ...

  3. 添加用户username到sudo组

    添加用户username到sudo组: usermod -aG sudo username USERMOD(8) 系统管理命令 USERMOD(8) 名 usermod - 修改一个用户账户 大 us ...

  4. 洛谷P4931 情侣!给我!烧了! 数论

    正解:数论 解题报告: 传送门 这题,想不到就很痛苦,但是理解了之后还是觉得也没有很难,,,毕竟实现不难QAQ 首先关于前面k对情侣的很简单,就是C(n,k)*C(n,k)*A(k,k)*2k 随便解 ...

  5. 第k小数据

    给定两个整型数组A和B(未排序).我们将A和B中的元素两两相加可以得到数组C. 譬如A为[1,2],B为[3,4].那么由A和B中的元素两两相加得到的数组C为[4,5,5,6]. 现在给你数组A和B, ...

  6. 如何正确的把 Java 数组 Array 转为列表 List

    最近想把 java 数组转成 List,网上普遍的答案都是 Arrays.asList: String[] a = new String[] {"hello", "wor ...

  7. [py]django上线部署-uwsgi+nginx+py3/django1.10

    https://github.com/lannyMa/django-uwsgi-nginx.git 单机调试启动-确保项目代码没问题 - 克隆代码进入项目 git clone https://gith ...

  8. Elasticsearch Date类型使用技巧

    elasticsearch原生支持date类型.这里简单记录下使用的方法. 使用date类型可以用如下两种方式: 使用毫秒的时间戳,直接将毫秒值传入即可. 传入格式化的字符串,默认是ISO 8601标 ...

  9. 畅通工程续 (SPFA模板Floy模板)

    http://acm.hdu.edu.cn/showproblem.php?pid=1874 SPFA #include <iostream> #include <stdio.h&g ...

  10. SQL Server查询中特殊字符的处理方法

    SQL Server查询中,经常会遇到一些特殊字符,比如单引号“'”等,这些字符的处理方法,是SQL Server用户都应该需要知道的. 我们都知道SQL Server查询过程中,单引号“'”是特殊字 ...