【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 +=$ ...
随机推荐
- Java 向Hbase表插入数据报(org.apache.hadoop.hbase.client.HTablePool$PooledHTable cannot be cast to org.apac
org.apache.hadoop.hbase.client.HTablePool$PooledHTable cannot be cast to org.apac 代码: //1.create HTa ...
- ping命令使用技巧(一次Ping多个地址)
打开windows 命令行 窗口, 在命令行输入以下命令: for /l %i in (1,1,255) do ping -n 1 -w 60 192.168.0.%i | find " ...
- java工程开发之图形化界面之(第一课)
下面我们先上代码: package 一个事例图形小应用程序; import javax.swing.JApplet; import java.awt.Graphics; public class 绘制 ...
- 剑指offer 连续子序列和
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Solution { public: int FindGreatestSumOfSu ...
- Entity Framework 学习初级篇7--基本操作:增加、更新、删除、事务
本节,直接写通过代码来学习.这些基本操作都比较简单,与这些基本操作相关的内容在之前的1至6节基本介绍完毕. l 增加: 方法1:使用AddToXXX(xxx)方法:实例代码如下: ...
- Android -----ArrayAdapter的重写 .
引自:http://blog.csdn.net/jason0539/article/details/9918465 最近需要用ArrayAdapter,保存一下,以后方便查找 ArrayAdapter ...
- html常见标签使用
<body> <!--标题标签--> <h1></h1> <h2></h2> <h3></h3> < ...
- 转:Visual Studio进行Web性能测试- Part I
原文作者:Ambily.raj Visual Studio是可以用于性能测试的工具之一.Visual Studio Test版或Visual Studio 2010旗舰版为自动化测试提供了支持.本文介 ...
- HDU 3201 Build a Fence
水题 #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> us ...
- db2 sqlcode
DB2错误信息(按sqlcode排序) sqlcode sqlstate 说明 000 00000 SQL语句成功完成 01xxx SQL语句成功完成,但是有警告 +012 01545 未限定的列名被 ...