【NOIP2015】反思+题解
D1T1> 神奇的幻方
模拟即可。
- #include <cstdio>
- #include <cstring>
- #include <algorithm>
- #define rep(i, a, b) for (int i = a; i <= b; i++)
- #define drep(i, a, b) for (int i = a; i >= b; i--)
- #define REP(i, a, b) for (int i = a; i < b; i++)
- #define pb push_back
- #define mp make_pair
- #define clr(x) memset(x, 0, sizeof(x))
- #define xx first
- #define yy second
- using namespace std;
- typedef long long i64;
- typedef pair<int, int> pii;
- const int inf = ~0U >> ;
- const i64 INF = ~0ULL >> ;
- //******************************
- int map[][];
- int main() {
- int n;
- scanf("%d", &n);
- pii last = mp(, n / + );
- map[][n / + ] = ;
- rep(i, , n * n) {
- if (last.xx == && last.yy != n) {
- map[n][last.yy + ] = i;
- last = mp(n, last.yy + );
- }
- else if (last.yy == n && last.xx != ) {
- map[last.xx - ][] = i;
- last = mp(last.xx - , );
- }
- else if (last.xx == && last.yy == n) {
- map[last.xx + ][last.yy] = i;
- last = mp(last.xx + , last.yy);
- }
- else if (last.xx != && last.yy != n && !map[last.xx - ][last.yy + ]) {
- map[last.xx - ][last.yy + ] = i;
- last = mp(last.xx - , last.yy + );
- }
- else {
- map[last.xx + ][last.yy] = i;
- last = mp(last.xx + , last.yy);
- }
- }
- rep(i, , n) {
- rep(j, , n) {
- if (j != ) printf(" ");
- printf("%d", map[i][j]);
- }
- puts("");
- }
- return ;
- }
D1T2> 信息传递
一个点只有一个出度 => 环不会交叉
1)dfs找环 2)tarjan找scc
考试的时候就直接写了tarjan...
- #include <cstdio>
- #include <cstring>
- #include <algorithm>
- #define rep(i, a, b) for (int i = a; i <= b; i++)
- #define drep(i, a, b) for (int i = a; i >= b; i--)
- #define REP(i, a, b) for (int i = a; i < b; i++)
- #define pb push_back
- #define mp make_pair
- #define clr(x) memset(x, 0, sizeof(x))
- #define xx first
- #define yy second
- using namespace std;
- typedef long long i64;
- typedef pair<int, int> pii;
- const int inf = ~0U >> ;
- const i64 INF = ~0ULL >> ;
- //******************************
- const int maxn = ;
- struct Ed {
- int u, v, nx; Ed() {}
- Ed(int _u, int _v, int _nx)
- :u(_u), v(_v), nx(_nx) {}
- } a[maxn];
- int fst[maxn], cnt;
- void addedge(int u, int v) {
- a[++cnt] = Ed(u, v, fst[u]);
- fst[u] = cnt;
- }
- int dfn[maxn], low[maxn], Index, vis[maxn];
- int stack[maxn], top;
- int scc_cnt;
- int belong[maxn], size[maxn];
- void tarjan(int u) {
- dfn[u] = low[u] = ++Index;
- vis[u] = ;
- stack[++top] = u;
- for (int i = fst[u]; i; i = a[i].nx) {
- int v = a[i].v;
- if (!dfn[v]) {
- tarjan(v);
- low[u] = min(low[u], low[v]);
- }
- else if (vis[v]) {
- low[u] = min(low[u], dfn[v]);
- }
- }
- if (dfn[u] == low[u]) {
- scc_cnt++;
- while (stack[top] != u) {
- belong[stack[top]] = scc_cnt;
- vis[stack[top]] = ;
- size[scc_cnt]++;
- top--;
- }
- belong[stack[top]] = scc_cnt;
- vis[stack[top]] = ;
- size[scc_cnt]++;
- top--;
- }
- }
- int main() {
- int n;
- scanf("%d", &n);
- rep(i, , n) {
- int id;
- scanf("%d", &id);
- addedge(i, id);
- }
- rep(i, , n) {
- if (!dfn[i]) tarjan(i);
- }
- int ans = 0x3f3f3f3f;
- rep(i, , scc_cnt) if (size[i] != ) ans = min(ans, size[i]);
- printf("%d\n", ans);
- return ;
- }
D1T3> 斗地主
搜索题,以前在contest hunter上见过,没有订正...
因为1 2 3 4 5不能顺, 1 1 1 2 2 2不能连出,可以在读入时将牌的编号重新分配,只需要将 A 调整到 K 后,2 和 A 断开即可。
考试的时候想把所有可行的方案预处理出来,压位压在一起,然后状压dp,这样是不可行的,因为方案数多了后时间复杂度会爆炸。
以下代码可以过NOIP官方数据,但是过不了UOJ的加强版题目,会WA,这篇代码的思路主要是在每次判断时,人为地把4张和3张出掉,强剪枝。
- #include <bits/stdc++.h>
- #define rep(i, a, b) for (register int i = a; i <= b; i++)
- #define drep(i, a, b) for (register int i = a; i >= b; i--)
- #define REP(i, a, b) for (int i = a; i < b; i++)
- #define pb push_back
- #define mp make_pair
- #define clr(x) memset(x, 0, sizeof(x))
- #define xx first
- #define yy second
- using namespace std;
- typedef long long i64;
- typedef pair<int, int> pii;
- const int inf = ~0U >> ;
- const i64 INF = ~0ULL >> ;
- //********************************
- const int maxn = ;
- inline int read() {
- int l = , s = ;
- char ch = getchar();
- while (ch < '' || ch > '') { if (ch == '-') l = -; ch = getchar(); }
- while (ch >= '' && ch <= '') { s = (s << ) + (s << ) + ch - ''; ch = getchar(); }
- return l * s;
- }
- int poker[maxn];
- int ans = inf;
- void dfs(int);
- void group(int base, int len, int dep) {
- rep(st, , - len) {
- if (poker[st] < base) continue;
- int end;
- for (end = st; end <= ; end++) if (poker[end] < base) break;
- if (--end - st + < len) continue;
- drep(k, end, st + len - ) {
- rep(i, st, k) poker[i] -= base;
- poker[] -= (k - st + ) * base;
- dfs(dep + );
- rep(i, st, k) poker[i] += base;
- poker[] += (k - st + ) * base;
- }
- }
- }
- int n, tong[maxn];
- void dfs(int dep) {
- if (dep > ans) return;
- if (poker[] == ) return;
- rep(i, , ) tong[poker[i]]++;
- int sum();
- while (tong[] > ) {
- sum++;
- tong[]--;
- if (tong[] >= ) tong[] -= ;
- else if (tong[] >= ) tong[] -= ;
- }
- while (tong[] > ) {
- sum++;
- tong[]--;
- if (tong[] >= ) tong[] -= ;
- else if (tong[] >= ) tong[] -= ;
- }
- if (tong[] >= && poker[] >= && poker[] >= ) sum--;
- if (sum + tong[] + tong[] + dep < ans) ans = sum + tong[] + tong[] + dep;
- tong[] = tong[] = ;
- group(, , dep);
- group(, , dep);
- group(, , dep);
- }
- int main() {
- int T;
- T = read(), n = read();
- while (T--) {
- memset(poker, , sizeof(poker));
- rep(i, , n) {
- int rb, id;
- id = read(); rb = read();
- if (id >= && id <= ) poker[id - ]++;
- else if (id == ) poker[]++;
- else if (id == ) poker[]++;
- else if (id == && poker[] == ) poker[]++;
- else poker[]++;
- }
- poker[] = n;
- ans = inf;
- dfs();
- printf("%d\n", ans);
- }
- return ;
- }
这一篇代码依然可以过NOIP官方数据,但是在UOJ加强版上在第9个extra test上t了,不知道卡时是否可以。
这个思路考虑了 AAAA2222 在一次出完的情况, 还考虑了在4带2时可以破坏3个一样的牌的情况,分别写出来就好了。
- #include <bits/stdc++.h>
- #define rep(i, a, b) for (int i = a; i <= b; i++)
- #define drep(i, a, b) for (int i = a; i >= b; i--)
- #define REP(i, a, b) for (int i = a; i < b; i++)
- #define pb push_back
- #define mp make_pair
- #define clr(x) memset(x, 0, sizeof(x))
- #define xx first
- #define yy second
- using namespace std;
- typedef long long i64;
- typedef pair<int, int> pii;
- const int inf = ~0U >> ;
- const i64 INF = ~0ULL >> ;
- //********************************
- const int maxn = ;
- int poker[maxn];
- int ans = inf;
- void dfs(int dep, int order) {
- if (dep > ans) return;
- if (dep + poker[] < ans) ans = dep + poker[];
- if (poker[] == ) return;
- //AAABBBCCC
- if (order <= )
- rep(st, , ) {
- if (poker[st] < ) continue;
- int end;
- for (end = st; end <= ; end++) if (poker[end] < ) break;
- end--; if (end - st < ) break;
- rep(k, st + , end) {
- rep(i, st, k) poker[i] -= ;
- poker[] -= (k - st + ) * ;
- dfs(dep + , );
- rep(i, st, k) poker[i] += ;
- poker[] += (k - st + ) * ;
- }
- }
- //AABBCC
- if (order <= )
- rep(st, , ) {
- if (poker[st] < ) continue;
- int end;
- for (end = st; end <= ; end++) if (poker[end] < ) break;
- end--; if (end - st + < ) continue;
- rep(k, st + , end) {
- rep(i, st, k) poker[i] -= ;
- poker[] -= (k - st + ) * ;
- dfs(dep + , );
- rep(i, st, k) poker[i] += ;
- poker[] += (k - st + ) * ;
- }
- }
- //ABCDE
- if (order <= )
- rep(st, , ) {
- if (poker[st] < ) continue;
- int end;
- for (end = st; end <= ; end++) if (poker[end] < ) break;
- end--; if (end - st + < ) continue;
- rep(k, st + , end) {
- rep(i, st, k) poker[i] -= ;
- poker[] -= k - st + ;
- dfs(dep + , );
- rep(i, st, k) poker[i] += ;
- poker[] += k - st + ;
- }
- }
- //AAAABC
- if (order <= )
- rep(st, , ) {
- if (poker[st] < ) continue;
- rep(i, , ) {
- if (poker[i] < || i == st) continue;
- poker[i] -= ;
- rep(j, i, ) {
- if (poker[j] < || j == st) continue;
- poker[st] -= ; poker[j] -= ;
- poker[] -= ;
- dfs(dep + , );
- poker[st] += ; poker[j] += ;
- poker[] += ;
- }
- poker[i] += ;
- }
- }
- //AAAABBCC
- if (order <= )
- rep(st, , ) {
- if (poker[st] < ) continue;
- rep(i, , ) {
- if (poker[i] < || i == st) continue;
- poker[i] -= ;
- rep(j, i, ) {
- if (poker[j] < || j == st) continue;
- poker[st] -= , poker[j] -= ;
- poker[] -= ;
- dfs(dep + , );
- poker[st] += , poker[j] += ;
- poker[] += ;
- }
- poker[i] += ;
- }
- }
- //AAABB
- if (order <= )
- rep(st, , ) {
- if (poker[st] < ) continue;
- rep(i, , ) {
- if (poker[i] < || i == st) continue;
- poker[st] -= , poker[i] -= ;
- poker[] -= ;
- dfs(dep + , );
- poker[st] += , poker[i] += ;
- poker[] += ;
- }
- }
- //AAAB
- if (order <= )
- rep(st, , ) {
- if (poker[st] < ) continue;
- rep(i, , ) {
- if (poker[i] < || i == st) continue;
- poker[st] -= , poker[i] -= ;
- poker[] -= ;
- dfs(dep + , );
- poker[st] += , poker[i] += ;
- poker[] += ;
- }
- }
- //AAAA
- if (order <= )
- rep(st, , ) {
- if (poker[st] < ) continue;
- poker[st] -= , poker[] -= ;
- dfs(dep + , );
- poker[st] += , poker[] += ;
- }
- //AAA
- if (order <= )
- rep(st, , ) {
- if (poker[st] < ) continue;
- poker[st] -= , poker[] -= ;
- dfs(dep + , );
- poker[st] += , poker[] += ;
- }
- //AA
- if (order <= )
- rep(st, , ) {
- if (poker[st] < ) continue;
- poker[st] -= , poker[] -= ;
- dfs(dep + , );
- poker[st] += , poker[] += ;
- }
- //Joker
- if (order <= )
- if (poker[] && poker[]) {
- poker[] = poker[] = ;
- poker[] -= ;
- dfs(dep + , );
- poker[] = poker[] = ;
- poker[] += ;
- }
- }
- int main() {
- int T, n;
- scanf("%d%d", &T, &n);
- while (T--) {
- memset(poker, , sizeof(poker));
- rep(i, , n) {
- int rb, id;
- scanf("%d%d", &id, &rb);
- if (id >= && id <= ) poker[id - ]++;
- else if (id == ) poker[]++;
- else if (id == ) poker[]++;
- else if (id == && poker[] == ) poker[]++;
- else poker[]++;
- }
- poker[] = n;
- ans = inf;
- dfs(, );
- printf("%d\n", ans);
- }
- return ;
- }
D2T1> 跳石头
二分+贪心。
noi.openjudge.cn的原题,首先二分答案,在二分答案的情况下,扫一遍n个石头,如果这个石头与前一个石头的距离小于二分的答案,那么就把前一个石头取消。
- #include <cstdio>
- #include <cstring>
- #include <algorithm>
- #define rep(i, a, b) for (int i = a; i <= b; i++)
- #define drep(i, a, b) for (int i = a; i >= b; i--)
- #define REP(i, a, b) for (int i = a; i < b; i++)
- #define pb push_back
- #define mp make_pair
- #define clr(x) memset(x, 0, sizeof(x))
- #define xx first
- #define yy second
- using namespace std;
- typedef long long i64;
- typedef pair<int, int> pii;
- const int inf = ~0U >> ;
- const i64 INF = ~0ULL >> ;
- //******************************
- int map[][];
- int main() {
- int n;
- scanf("%d", &n);
- pii last = mp(, n / + );
- map[][n / + ] = ;
- rep(i, , n * n) {
- if (last.xx == && last.yy != n) {
- map[n][last.yy + ] = i;
- last = mp(n, last.yy + );
- }
- else if (last.yy == n && last.xx != ) {
- map[last.xx - ][] = i;
- last = mp(last.xx - , );
- }
- else if (last.xx == && last.yy == n) {
- map[last.xx + ][last.yy] = i;
- last = mp(last.xx + , last.yy);
- }
- else if (last.xx != && last.yy != n && !map[last.xx - ][last.yy + ]) {
- map[last.xx - ][last.yy + ] = i;
- last = mp(last.xx - , last.yy + );
- }
- else {
- map[last.xx + ][last.yy] = i;
- last = mp(last.xx + , last.yy);
- }
- }
- rep(i, , n) {
- rep(j, , n) {
- if (j != ) printf(" ");
- printf("%d", map[i][j]);
- }
- puts("");
- }
- return ;
- }
D2T2> 子串
dp。
用f[i][j][k][2]表示第一个字符串中的前i位,取出k段,按顺序组合,拼出第二个字符串前j位的方案数,最后一位若为1则表示第i位被考虑在内(被选取),为0则为不被选取。
那么当S[i] == T[j]时(S 为 第一个字符串,T 为 第二个字符串)
f[i][j][k][1] = f[i - 1][j - 1][k][1] + f[i - 1][j - 1][k - 1][0] + f[i - 1][j - 1][k - 1][1];
f[i][j][k][0] = f[i - 1][j][k][0];
否则 f[i][j][k][1] = 0, f[i][j][k][0] = f[i - 1][j][k][0] + f[i - 1][j][k][1];
解释:当前字符能否接下去(假若S[i] ==T[j])实则取决于第i - 1个字符是否选取。
- #include <bits/stdc++.h>
- #define rep(i, a, b) for (int i = a; i <= b; i++)
- #define drep(i, a, b) for (int i = a; i >= b; i--)
- #define REP(i, a, b) for (int i = a; i < b; i++)
- #define pb push_back
- #define mp make_pair
- #define clr(x) memset(x, 0, sizeof(x))
- #define xx first
- #define yy second
- using namespace std;
- typedef long long i64;
- typedef pair<int, int> pii;
- const int inf = ~0U >> ;
- const i64 INF = ~0ULL >> ;
- //*******************************
- const int maxn = , maxm = ;
- const int mod = ;
- int read() {
- int s = , l = ;
- char ch = getchar();
- while (ch < '' || ch > '') { if (ch == '-') l = -; ch = getchar(); }
- while (ch >= '' && ch <= '') { s = (s << ) + (s << ) + ch - ''; ch = getchar(); }
- return l * s;
- }
- char str1[maxn], str2[maxm];
- i64 f[][maxm][maxm][];
- int main() {
- int n, m, k;
- n = read(), m = read(), k = read();
- scanf("%s%s", str1 + , str2 + );
- f[][][][] = f[][][][] = ;
- int flag = ;
- rep(i, , n) {
- flag ^= ;
- int up = min(i, m);
- rep(j, , up) {
- if (str1[i] == str2[j]) rep(kk, , j) {
- f[flag][j][kk][] = (f[ ^ flag][j][kk][] + f[ ^ flag][j][kk][]) % mod;
- f[flag][j][kk][] = (f[ ^ flag][j - ][kk][] + f[ ^ flag][j - ][kk - ][] + f[ ^ flag][j - ][kk - ][]) % mod;
- }
- else rep(kk, , j) {
- f[flag][j][kk][] = (f[ ^ flag][j][kk][] + f[ ^ flag][j][kk][]) % mod;
- f[flag][j][kk][] = ;
- }
- }
- }
- printf("%lld\n", (f[flag][m][k][] + f[flag][m][k][]) % mod);
- return ;
- }
D2T3> 运输计划
两天内改完......
总结:考得挺扯蛋的,335,非常不满意:(
暴力分没有拿全,对算法的掌握不够深刻,最恶心的是做过的题也不会。
这TM混蛋的人生又干掉了我的希望,就这样吧,也没什么好说的...
【NOIP2015】反思+题解的更多相关文章
- NOIP2015斗地主题解 7.30考试
问题 B: NOIP2015 斗地主 时间限制: 3 Sec 内存限制: 1024 MB 题目描述 牛牛最近迷上了一种叫斗地主的扑克游戏.斗地主是一种使用黑桃.红心.梅花.方片的A到K加上大小王的共 ...
- [CSP-S模拟测试50]反思+题解
??大部分人都觉得T3是道不可做题去刚T1T2了,于是我就侥幸苟到了前面? 这场考试比较成功的就是快速水掉了T1T2的部分分,1h拿到88分起码为之后硬肝T3上了保险(赛后发现就算T3爆零也能rank ...
- 【NOIP2015资源+题解】
数据下载(含cena配置文件+一套自己写的代码) 试题下载(pdf版) Day1 T1 Day1 T2 Day1 T3 Day2 T1 Day2 T2 Day3 T3
- [NOIP2015]子串 题解
题目描述 有两个仅包含小写英文字母的字符串A和B. 现在要从字符串A中取出k个互不重叠的非空子串,然后把这 k 个子串按照其在字符串 A 中出现的顺序依次连接起来得到一个新的字符串,请问有多少种方案可 ...
- [CSP-S模拟测试48]反思+题解
状态很垃圾的一场考试.感觉“这么多分就够了”的心态很是在给自己拖后腿. 打开题面,第一页赫然写着:$Claris' Contest$. 吓得我差点手一抖关掉.不过后来想想似乎强到变态的人出的题都不是很 ...
- [CSP-S模拟测试47]反思+题解
打开题面,T3似乎被换过了.(那我就更有理由直接弃掉了) T1是我最害怕的乱搞题,赶紧扔了看T2.发现是个sb板子?雨天的尾巴弱化版? 然而线段树合并早忘干净了(最近几道可以线段树合并的题都是用别的方 ...
- [NOIP模拟测试37]反思+题解
一定要分析清楚复杂度再打!!!窝再也不要花2h20min用暴力对拍暴力啦!!! 雨露均沾(滑稽),尽量避免孤注一掷.先把暴力分拿全再回来刚正解. 即使剩下的时间不多了也优先考虑认真读题+打暴力而非乱搞 ...
- [NOIP模拟测试34]反思+题解
不要陷入思维定势,如果长时间没有突破就要考虑更改大方向. 不要把简单问题复杂化. 做完的题就先放下,不管能拿多少分.不能过一段时间就回来调一下. $Solutions:$ A.次芝麻 因为$n+m$始 ...
- [NOIP模拟33]反思+题解
又考了一次降智题…… 拿到T1秒出正解(可能是因为我高考数学数列学的海星?),分解质因数以后用等比数列求和计算每个因子的贡献.但是当时太过兴奋把最后的$ans \times =$打成了$ans +=$ ...
随机推荐
- static加载问题
原文地址:http://blog.csdn.net/lubiaopan/article/details/4802430 感谢原作者! static{}(即static块),会在类被加载的时候执 ...
- git rebase 使用
git rebase 不会取回代码 要用git fetch先取回, git rebase 是合并代码. (1)首先用git fetch返回服务器上的代码 (2)首先用git rebase origin ...
- 初学HTML5的一点理解
刚接触了一点点用h5移动端的一点知识,用自己最浅薄的理解来看解决自适应屏幕尺寸问题和适应屏幕尺寸的布局问题.这里,为了解决自适应屏幕尺寸问题大概需要做的就是把HTML中的元素的尺寸尽可能的用百分比表示 ...
- AngularJs: Reload page
<a ng-click="reloadRoute()" class="navbar-brand" title="home" data- ...
- Tomcat数据源
Tomcat数据源原理,配置,使用 在程序中,使用数据源是可以提升操作性能的,这种性能 的提升依靠运行的操作原理. 传统的JDBC操作: 1. 加载数据库驱动,通过CLASSPATH配置 2. 通过D ...
- C# 经典入门11章,比较
1类型比较 所有的类懂从System.Object中继承了GetType()方法,这个方法和typeof()运算符一起使用,可以确定对象的类型.例如: if(myObj.GetType()==type ...
- 集合-字典(Dictionary)
字典(散列表):允许按照某个键来访问元素,能根据键快速查找元素,也可以自由添加,删除元素.比较像List<T>类,但没有list向后移动元素的性能开销. .net中最主要的字典类是Dict ...
- XML简单的增改删操作
XML文件的简单增改删,每一个都可以单独拿出来使用. 新创建XML文件,<?xmlversion="1.0"encoding="utf-8"?> & ...
- adb shell 命令详解,android
http://www.miui.com/article-275-1.html http://noobjava.iteye.com/blog/1914348 adb shell 命令详解,android ...
- 简单三段式状态机实验3-Sequence Detect(序列检测)
1.序列检测器的逻辑功能描述:序列检测指的就是将一个指定的序列从数字码流中识别出来.本例中,我们将设计一个"10010”序列的检测器.设x_in为数字码流输入,z_out为检出标记输出,高电 ...