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的主要内容,如果未能解决你的问题,请参考以下文章

2015 Noip提高组 Day1

Noip2015 提高组 Day1

信息传递 NOIP2015 day1 T2

斗地主 (NOIP2015 Day1 T3)

NOIP2015提高组Day1题解

斗地主(Noip2015Day1T3)