NOIP 2015 day1
Posted Ariel_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NOIP 2015 day1相关的知识,希望对你有一定的参考价值。
pts:300
T1: 100
T2: 100
T3: 100
[NOIP2015 提高组] 神奇的幻方
模拟
emm,没啥说的
[NOIP2015 提高组] 信息传递
图论
Tarjan 板子
/*
work by:Ariel_
*/
#include <iostream>
#include <cstdio>
using namespace std;
const int N = 2e5 + 5;
int read(){
int x = 0,f = 1; char c = getchar();
while(c < \'0\'||c > \'9\') {if(c == \'-\') f = -1; c = getchar();}
while(c >= \'0\' && c <= \'9\') {x = x*10 + c - \'0\'; c = getchar();}
return x*f;
}
int n, Ans = 0x3f3f3f3f, dfn[N], low[N], tot, cnt, siz[N], ins[N], st[N], tp, head[N], E;
struct edge{int v, nxt;}e[N];
void add_edge(int u, int v) {
e[++E] = (edge){v, head[u]};
head[u] = E;
}
void Tarjan(int x) {
dfn[x] = low[x] = ++tot;
st[++tp] = x, ins[x] = 1, siz[x] = 1;
for (int i = head[x]; i; i = e[i].nxt) {
int v = e[i].v;
if(!dfn[v]) {
Tarjan(v);
low[x] = min(low[x], low[v]);
}
else if(ins[v]) low[x] = min(dfn[v], low[x]);
}
if (low[x] == dfn[x]) {
cnt++;
while(1){
int k = st[tp--];
if (k == x) break; siz[cnt]++;
}
}
}
int main(){
n = read();
for (int i = 1, x; i <= n; i++) x = read(), add_edge(i, x);
for (int i = 1; i <= n; i++) if (!dfn[i]) Tarjan(i);
for (int i = 1; i <= cnt; i++) if (siz[i] > 1) Ans = min(Ans, siz[i]);
printf("%d\\n", Ans);
return 0;
}
[NOIP2015 提高组] 斗地主
爆搜
/*
work by:Ariel_
斗地主大纲
*/
//#include <bits/stdc++.h>
//using namespace std;
//
//void work(int stp) {
// if(ans > stp) stop;
// 单顺子, 用个计数器统计顺子牌的数量
// for(牌)
// 如果某个牌 = 0,计数器就归 0
// 如果牌数 >= 5 把顺子出出去,然后递归出牌
// 回溯
// 双顺子
// for (牌)
// 如果某个牌 < 2,计数器清零
// 如果牌数 >= 3 把顺子出出去,然后递归出牌
// 回溯
// 三顺子
// for (牌)
// 如果某个牌 < 3,计数器清零
// 如果牌数 >= 2, 计数器清零
// 带牌
// 三带一,二
// for (牌)
// 如果某个牌 == 3
// P[某个牌] -= 3;
// for (牌)
// 如果某个牌 >= 1
// 出牌
// 回溯
// for (牌)//三带二
// 如果某个牌 >= 2
// 出牌
// 回溯
// P[某个牌] += 3
// 四张牌
// 可以选择出三张,和上面一个样
// 四带二/二对
// P[牌] -= 4
// for (牌)
// P[某张牌] >= 1 带牌 1
// for (牌)
// P[某张牌] >= 1 带牌 2
// 回溯
// 回溯
// for (牌)
// P[某张牌] >= 2 带牌 1
// for (牌)
// P[某张牌] >= 2 带牌 2
// 回溯
// 回溯
// P[牌] += 4;(回溯)
// for (牌) 如果某个牌有剩余,直接都出出去,stp++;
// ans = min(ans, stp);
//}
//int main(){
// //T,n
// //读入牌,用数组统计每种牌的个数,大王小王用 15 表示, A 用 14 表示(正常斗地主插牌方式)
// //开始搜索出牌 work(step)
//}
/*
work by:Ariel_
10:00 过了样例 睡觉
*/
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <algorithm>
using namespace std;
const int N = 30;
int read(){
int x = 0,f = 1; char c = getchar();
while(c < \'0\'||c > \'9\') {if(c == \'-\') f = -1; c = getchar();}
while(c >= \'0\' && c <= \'9\') {x = x*10 + c - \'0\'; c = getchar();}
return x*f;
}
int T, n, P[N], Ans = 0x3f3f3f3f;
void clear(){memset(P, 0, sizeof P), Ans = 0x3f3f3f3f;}
void work(int stp) {
if (stp >= Ans) return ;
int tot = 0;
for (int i = 3; i <= 14; i++) {//单顺子
if (!P[i]) tot = 0;
else {
tot++;
if (tot >= 5){
for (int j = i; j >= i - tot + 1; j--) P[j]--;
work(stp + 1);
for (int j = i; j >= i - tot + 1; j--) P[j]++;
}
}
}
tot = 0;
for (int i = 3; i <= 14; i++) {//双顺子
if (P[i] < 2) tot = 0;
else {
tot++;
if (tot >= 3) {
for (int j = i; j >= i - tot + 1; j--) P[j] -= 2;
work (stp + 1);
for (int j = i; j >= i - tot + 1; j--) P[j] += 2;
}
}
}
tot = 0;
for (int i = 3; i <= 14; i++) {//三顺子
if (P[i] < 3) tot = 0;
else {
tot++;
if (tot >= 2) {
for (int j = i; j >= i - tot + 1; j--) P[j] -= 3;
work(stp + 1);
for (int j = i; j >= i - tot + 1; j--) P[j] += 3;
}
}
}
for (int i = 2; i <= 14; i++) {//三带一/二
if (P[i] <= 3) {
if (P[i] <= 2) continue;
P[i] -= 3;
for (int j = 2; j <= 15; j++) {
if (P[j] <= 0 || j == i) continue;
P[j]--, work(stp + 1), P[j]++;
}
for (int j = 2; j <= 14; j++) {
if (P[j] < 2 || j == i) continue;
P[j] -= 2, work(stp + 1), P[j] += 2;
}
P[i] += 3;
}
else {
P[i] -= 3;
for (int j = 2; j <= 15; j++) {
if (!P[j]|| j == i) continue;
P[j]--, work(stp + 1), P[j]++;
}
for (int j = 2; j <= 14; j++){
if (P[j] <= 1|| j == i) continue;
P[j] -= 2, work(stp + 1), P[j] += 2;
}
P[i] += 3, P[i] -= 4;//四带二
for (int j = 2; j <= 15; j++) {
if (!P[j]|| i == j) continue;
P[j]--;
for (int k = 2; k <= 15; k++) {
if (!P[k] || k == j) continue;
P[k]--, work(stp + 1), P[k]++;
}
P[j]++;
}
for (int j = 2; j <= 14; j++) {
if (P[j] <= 1 || i == j) continue;
P[j] -= 2;
for (int k = 2; k <= 14; k++) {
if (P[k] <= 1 || k == j) continue;
P[k] -= 2, work(stp + 1), P[k] += 2;
}
P[j] += 2;
}
P[i] += 4;
}
}
for (int i = 2;i <= 15; i++) if(P[i]) stp++;
Ans = min(Ans, stp);
}
int main(){
T = read(), n = read();
while(T--) {
clear();
for (int i = 1, num, fag; i <= n; i++) {
num = read(), fag = read();
if (num == 1) P[14]++;
else if(!num) P[15]++;
else P[num]++;
}
work(0);
printf("%d\\n", Ans);
}
return 0;
}
以上是关于NOIP 2015 day1的主要内容,如果未能解决你的问题,请参考以下文章