noip2010 真题练习 2017.2.18



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

Code

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cctype>
 4 #include<cstring>
 5 #include<cstdlib>
 6 #include<fstream>
 7 #include<sstream>
 8 #include<algorithm>
 9 #include<map>
10 #include<set>
11 #include<queue>
12 #include<vector>
13 #include<stack>
14 using namespace std;
15 typedef bool boolean;
16 #define INF 0xfffffff
17 #define smin(a, b) a = min(a, b)
18 #define smax(a, b) a = max(a, b)
19 template<typename T>
20 inline void readInteger(T& u){
21     char x;
22     int aFlag = 1;
23     while(!isdigit((x = getchar())) && x != ‘-‘);
24     if(x == ‘-‘){
25         x = getchar();
26         aFlag = -1;
27     }
28     for(u = x - ‘0‘; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - ‘0‘);
29     ungetc(x, stdin);
30     u *= aFlag;
31 }
32
33 int n, m;
34 int top;
35 int *s;
36 boolean exist[1002];
37
38 inline void s_push(int* sta, int x) {
39     exist[sta[top] + 1] = false;
40     sta[top] = x;
41     exist[x + 1] = true;
42     if(top == m - 1)    top = 0;
43     else top = top + 1;
44 }
45
46 int res = 0;
47 inline void solve() {
48     readInteger(m);
49     readInteger(n);
50     s = new int[(const int)(m + 1)];
51     memset(s, -1, sizeof(int) * (m + 1));
52     top = 0;
53     for(int i = 1, a; i <= n; i++) {
54         readInteger(a);
55         if(!exist[a + 1]) {
56             res++;
57             s_push(s, a);
58         }
59     }
60     printf("%d", res);
61 }
62
63 int main() {
64     freopen("translate.in", "r", stdin);
65     freopen("translate.out", "w", stdout);
66     solve();
67     return 0;
68 }




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

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

Code

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cctype>
 4 #include<cstring>
 5 #include<cstdlib>
 6 #include<fstream>
 7 #include<sstream>
 8 #include<algorithm>
 9 #include<map>
10 #include<set>
11 #include<queue>
12 #include<vector>
13 #include<stack>
14 using namespace std;
15 typedef bool boolean;
16 #define INF 0xfffffff
17 #define smin(a, b) a = min(a, b)
18 #define smax(a, b) a = max(a, b)
19 template<typename T>
20 inline void readInteger(T& u){
21     char x;
22     int aFlag = 1;
23     while(!isdigit((x = getchar())) && x != ‘-‘);
24     if(x == ‘-‘){
25         x = getchar();
26         aFlag = -1;
27     }
28     for(u = x - ‘0‘; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - ‘0‘);
29     ungetc(x, stdin);
30     u *= aFlag;
31 }
32
33 int n, m;
34 int counter[4];
35 int f[41][41][41][41];
36 boolean vis[41][41][41][41];
37 int *val;
38
39 inline void init() {
40     readInteger(n);
41     readInteger(m);
42     memset(counter, 0, sizeof(counter));
43     memset(f, 0, sizeof(f));
44     memset(vis, false, sizeof(vis));
45     val = new int[(const int)(n + 1)];
46     for(int i = 1; i <= n; i++)        readInteger(val[i]);
47     for(int i = 1, a; i <= m; i++) {
48         readInteger(a);
49         counter[a - 1]++;
50     }
51     f[0][0][0][0] = val[1];
52     vis[0][0][0][0] = true;
53 }
54
55 int dfs(int a, int b, int c, int d) {
56     if(vis[a][b][c][d])    return f[a][b][c][d];
57     vis[a][b][c][d] = true;
58     int pos = a * 1 + b * 2 + c * 3 + d * 4 + 1;
59     int ra = 0, rb = 0, rc = 0, rd = 0;
60     if(a > 0)    ra = dfs(a - 1, b, c, d);
61     if(b > 0)    rb = dfs(a, b - 1, c, d);
62     if(c > 0)    rc = dfs(a, b, c - 1, d);
63     if(d > 0)    rd = dfs(a, b, c, d - 1);
64     smax(f[a][b][c][d], max(ra, max(rb, max(rc, rd))) + val[pos]);
65     return f[a][b][c][d];
66 }
67
68 inline void solve() {
69     int res = dfs(counter[0], counter[1], counter[2], counter[3]);
70     printf("%d", res);
71 }
72
73 int main() {
74     freopen("tortoise.in", "r", stdin);
75     freopen("tortoise.out", "w", stdout);
76     init();
77     solve();
78     return 0;
79 }




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

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

Code

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cctype>
  4 #include<cstring>
  5 #include<cstdlib>
  6 #include<fstream>
  7 #include<sstream>
  8 #include<algorithm>
  9 #include<map>
 10 #include<set>
 11 #include<queue>
 12 #include<vector>
 13 #include<stack>
 14 using namespace std;
 15 typedef bool boolean;
 16 #define INF 0xfffffff
 17 #define smin(a, b) a = min(a, b)
 18 #define smax(a, b) a = max(a, b)
 19 template<typename T>
 20 inline void readInteger(T& u){
 21     char x;
 22     int aFlag = 1;
 23     while(!isdigit((x = getchar())) && x != ‘-‘);
 24     if(x == ‘-‘){
 25         x = getchar();
 26         aFlag = -1;
 27     }
 28     for(u = x - ‘0‘; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - ‘0‘);
 29     ungetc(x, stdin);
 30     u *= aFlag;
 31 }
 32
 33 typedef class Edge {
 34     public:
 35         int end;
 36         int next;
 37         int w;
 38         Edge(const int end = 0, const int next = 0, const int w = 0):end(end), next(next), w(w) {        }
 39 }Edge;
 40
 41 typedef class MapManager{
 42     public:
 43         int ce;
 44         int *h;
 45         Edge *edge;
 46         MapManager(){}
 47         MapManager(int points, int limit):ce(0){
 48             h = new int[(const int)(points + 1)];
 49             edge = new Edge[(const int)(limit + 1)];
 50             memset(h, 0, sizeof(int) * (points + 1));
 51         }
 52         inline void addEdge(int from, int end, int w){
 53             edge[++ce] = Edge(end, h[from], w);
 54             h[from] = ce;
 55         }
 56         inline void addDoubleEdge(int from, int end, int w){
 57             addEdge(from, end, w);
 58             addEdge(end, from, w);
 59         }
 60         Edge& operator [](int pos) {
 61             return edge[pos];
 62         }
 63 }MapManager;
 64 #define m_begin(g, i) (g).h[(i)]
 65
 66 int n, m;
 67 MapManager g;
 68 int* belong;
 69 int maxval = -1;
 70
 71 inline void init() {
 72     readInteger(n);
 73     readInteger(m);
 74     g = MapManager(n, 2 * m);
 75     belong = new int[(const int)(n + 1)];
 76     for(int i = 1, a, b, w; i <= m; i++) {
 77         readInteger(a);
 78         readInteger(b);
 79         readInteger(w);
 80         g.addDoubleEdge(a, b, w);
 81         smax(maxval, w);
 82     }
 83 }
 84
 85 boolean dfs(int node, int val, int x) {
 86     if(belong[node] != -1)    return belong[node] == val;
 87     else    belong[node] = val;
 88     for(int i = m_begin(g, node); i != 0; i = g[i].next) {
 89         if(g[i].w <= x)    continue;
 90         int& e = g[i].end;
 91         if(!dfs(e, val ^ 1, x))    return false;
 92     }
 93     return true;
 94 }
 95
 96 boolean check(int x) {
 97     memset(belong, -1, sizeof(int) * (n + 1));
 98     for(int i = 1; i <= n; i++) {
 99         if(belong[i] == -1)
100             if(!dfs(i, 0, x))    return false;
101     }
102     return true;
103 }
104
105 inline void solve() {
106     int l = 0, r = maxval;
107     while(l <= r) {
108         int mid = (l + r) >> 1;
109         if(!check(mid))    l = mid + 1;
110         else r = mid - 1;
111     }
112     printf("%d", r + 1);
113 }
114
115 int main() {
116     freopen("prison.in", "r", stdin);
117     freopen("prison.out", "w", stdout);
118     init();
119     solve();
120     return 0;
121 }




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

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

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

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

Code

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cctype>
  4 #include<cstring>
  5 #include<cstdlib>
  6 #include<fstream>
  7 #include<sstream>
  8 #include<algorithm>
  9 #include<map>
 10 #include<set>
 11 #include<queue>
 12 #include<vector>
 13 #include<stack>
 14 using namespace std;
 15 typedef bool boolean;
 16 #define INF 0xfffffff
 17 #define smin(a, b) a = min(a, b)
 18 #define smax(a, b) a = max(a, b)
 19 template<typename T>
 20 inline void readInteger(T& u){
 21     char x;
 22     int aFlag = 1;
 23     while(!isdigit((x = getchar())) && x != ‘-‘);
 24     if(x == ‘-‘){
 25         x = getchar();
 26         aFlag = -1;
 27     }
 28     for(u = x - ‘0‘; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - ‘0‘);
 29     ungetc(x, stdin);
 30     u *= aFlag;
 31 }
 32
 33 typedef class Point {
 34     public:
 35         int x, y;
 36         int l, r;
 37
 38         Point(const int x = 0, const int y = 0, const int l = 0, const int r = 0):x(x), y(y), l(l), r(r) {        }
 39
 40         boolean mergable(Point& b) {
 41             if(b.l < l)    return true;
 42             if(b.r > r)    return true;
 43             return false;
 44         }
 45         void merge(Point& b) {
 46             smin(l, b.l);
 47             smax(r, b.r);
 48         }
 49 }Point;
 50
 51 int n, m;
 52 int mat[505][505];
 53
 54 inline void init() {
 55     readInteger(n);
 56     readInteger(m);
 57     for(int i = 1; i <= n; i++) {
 58         for(int j = 1; j <= m; j++) {
 59             readInteger(mat[i][j]);
 60         }
 61     }
 62 }
 63
 64 const int mover[2][4] = {{0, 1, 0, -1}, {1, 0, -1, 0}};
 65
 66 Point f[505][505];
 67 boolean vis[505][505];
 68 Point dfs(int x, int y) {
 69     if(vis[x][y])    return f[x][y];
 70     vis[x][y] = true;
 71     f[x][y] = Point(x, y, 999, 0);
 72     if(x == n)    f[x][y] = Point(x, y, y, y);
 73     for(int k = 0; k < 4; k++) {
 74         int x1 = x + mover[0][k], y1 = y + mover[1][k];
 75         if(x1 < 1 || x1 > n)    continue;
 76         if(y1 < 1 || y1 > m)    continue;
 77         if(mat[x1][y1] < mat[x][y]) {
 78             Point e = dfs(x1, y1);
 79             f[x][y].merge(e);
 80         }
 81     }
 82     return f[x][y];
 83 }
 84
 85 void dfs1(int x, int y) {
 86     if(vis[x][y])    return;
 87     vis[x][y] = true;
 88     for(int k = 0; k < 4; k++) {
 89         int x1 = x + mover[0][k], y1 = y + mover[1][k];
 90         if(x1 < 1 || x1 > n)    continue;
 91         if(y1 < 1 || y1 > m)    continue;
 92         if(mat[x1][y1] < mat[x][y]) {
 93             Point e = dfs(x1, y1);
 94             f[x][y].merge(e);
 95         }
 96     }
 97 }
 98
 99 int *dp;
100 inline void solve() {
101     memset(vis, false, sizeof(vis));
102     for(int i = 1; i <= m; i++)
103         if(!vis[1][i])
104             dfs(1, i);
105     dp = new int[(const int)(m + 2)];
106     memset(dp, 0, sizeof(int) * (m + 2));
107     for(int i = 1; i <= m; i++)
108         if(f[1][i].l < 999)
109             dp[f[1][i].l] += 1, dp[f[1][i].r + 1] -= 1;
110     int unget = 0;
111     for(int i = 1; i <= m; i++) {
112         if(!vis[n][i])
113             unget++;
114     }
115     if(unget > 1) {
116         printf("0\n%d", unget);
117         return;
118     }
119     memset(dp, 0x7f, sizeof(int) * (m + 2));
120     dp[0] = 0;
121     for(int i = 1; i <= m; i++) {
122         for(int j = 1; j <= m; j++) {
123             if(f[1][j].l > i || f[1][j].r < i)    continue;
124             smin(dp[i], dp[f[1][j].l - 1] + 1);
125         }
126     }
127     printf("1\n%d", dp[m]);
128 }
129
130 int main() {
131     freopen("flow.in", "r", stdin);
132     freopen("flow.out", "w", stdout);
133     init();
134     solve();
135     return 0;
136 }
时间: 2024-10-26 02:31:49

noip2010 真题练习 2017.2.18的相关文章

蓝桥杯——计算机研究生机试真题(2017.2.20)

1. (2008年华中科技大学计算机研究生机试真题)八进制 题目描述: 输入一个整数,将其转换成八进制数输出. 输入: 输入包括一个整数N(0<=N<=100000). 输出: 可能有多组测试数据,对于每组数据, 输出N的八进制表示数. 样例输入: 7 8 9 样例输出: 7 10 11 法一:递归法: #include <stdio.h> void fun(int N) { if(N) { fun(N/8); printf("%d",N%8); } } int

noip2008 真题练习 2017.2.25

不是有很多可以说的,记住不能变算边取min Code 1 #include<iostream> 2 #include<fstream> 3 #include<sstream> 4 #include<cstdio> 5 #include<cctype> 6 #include<cstring> 7 #include<cstdlib> 8 #include<cmath> 9 #include<algorithm

系统架构设计师2009-2018历年综合知识、案例分析、论文真题及答案详细解析

https://blog.csdn.net/xxlllq/article/details/85049295 ??系统架构设计师复习资料当您看了这篇文章有何疑问,可先看最后的评论,有可能您遇到的问题其他人已经提出我已回复. 2018/12/14查询成绩后知道自己通过了系统架构设计师的考试(每科满分75,及格45分),特地记录一下.最终的成绩如下: 我是在9月份决定报名参加系统架构设计师考试,主要是想借此机会督促自己学习些除工作外的知识.准备了2个月,复习时间为周末,复习方式为看教学视频和真题练习.

网易2017春招笔试真题编程题集合题解

01 双核处理 题目 一种双核CPU的两个核能够同时的处理任务,现在有n个已知数据量的任务需要交给CPU处理,假设已知CPU的每个核1秒可以处理1kb,每个核同时只能处理一项任务.n个任务可以按照任意顺序放入CPU进行处理,现在需要设计一个方案让CPU处理完这批任务所需的时间最少,求这个最小的时间. 输入描述 输入包括两行:第一行为整数n(1 ≤ n ≤ 50)第二行为n个整数lengthi,表示每个任务的长度为length[i]kb,每个数均为1024的倍数. 输出描述输出一个整数,表示最少需

2017年广东省公务员录用考试《行测》真题及参考答案

2017年广东省公务员录用考试<行测>真题及参考答案 一.言语理解与表达.本部分包含选词填空和阅读理解 1.党的十八大以来,中央以猛药去疴.重典治乱的_____,以刮骨疗毒.壮士断腕的_____,不断加大党风廉政建设和巡视的力度,效果显著. 依次填入画横线部分最恰当的一项是: A.意念底气 B.恒心气势 C.意志气魄 D.决心勇气 2.这些亮相于世界互联网大会的中国创新成果,勾勒出未来生活的诱人______,也______着"创新中国"的蓬勃生机. 依次填入画横线部分最恰当

好未来2017秋招笔试真题二 --牛客网

好未来2017秋招笔试真题二 --牛客网 链接:https://www.nowcoder.com/questionTerminal/ee5de2e7c45a46a090c1ced2fdc62355来源:牛客网 将一句话的单词进行倒置,标点不倒置.比如 I like beijing. 经过函数后变为:beijing. like I 输入描述: 每个测试输入包含1个测试用例: I like beijing. 输入用例长度不超过100 输出描述: 依次输出倒置之后的字符串,以空格分割 输入例子: I

2017年软考各科最新真题详细解析资料集锦

作为51CTO学院的软考培训讲师,本着对广大学员负责的态度,在每年同学们参加完软考考试,我都会尽早的给大家发布各科的真题详细解析资料.一方面是为了参加软考考试的同学对自己考试情况做一个准确评估:另一方面是为未来参加软考考试的学员展现软考最新的考题形式,考察要点,助其有重点的复习软考考试. 历时多载,是同学们的坚定支持,才使我更加坚定,勇往直前,做更好的课程回馈大家. 现将最新的软考各科资料整理如下,同学们可以自行下载学习,学习过程中有疑问,也可给我留言. 一楼:软考网络工程师 2017年5月软考

2017年11月11日软考网络工程师案例分析真题及答案解析

[徐朋出品,必属精品]软考徐朋老师全网最先发布2017年11月11日软考网络工程师案例分析真题及答案解析,是全网最清新版本.详细讲解了2017年11月11日最新开考的软考网络工程师案例分析真题及答案.课件中对每一道真题都进行了详细的解析讲解,考后几周是学员记忆答案的最关键时间点,第一时间发布真题及答案帮助广大考生准确评估自己的考试结果及对未来参加考试的学员展示最新的考试趋势等.下载地址:http://down.51cto.com/data/2340424

2017年11月11日软考网络规划设计师案例分析真题及答案解析

[徐朋出品,必属精品]软考徐朋老师全网最先发布2017年11月11日软考网络规划设计师案例分析真题及答案解析,是全网最清新版本.详细讲解了2017年11月11日最新开考的软考网络规划设计师案例分析真题及答案.课件中对每一道真题都进行了详细的解析讲解,考后几周是学员记忆答案的最关键时间点,第一时间发布真题及答案帮助广大考生准确评估自己的考试结果及对未来参加考试的学员展示最新的考试趋势等.下载地址:http://down.51cto.com/data/2340406