noip2015 day1
不解释,很简单,直接按照题目的方法构造就行了
Code
1 #include<iostream> 2 #include<cstdio> 3 #include<cctype> 4 #include<cstring> 5 #include<map> 6 #include<set> 7 #include<queue> 8 #include<vector> 9 #include<algorithm> 10 using namespace std; 11 typedef bool boolean; 12 template<typename T> 13 inline void readInteger(T& u){ 14 char x; 15 while(!isdigit((x = getchar()))); 16 for(u = x - '0'; isdigit((x = getchar())); u = (u << 3) + (u << 1) + x - '0'); 17 ungetc(x, stdin); 18 } 19 20 template<typename T>class Matrix{ 21 public: 22 T* p; 23 int width; 24 int height; 25 Matrix():width(0), height(0){} 26 Matrix(int width, int height):width(width), height(height){ 27 p = new T[width * height]; 28 } 29 T* operator [](int pos){ 30 return p + pos * width; 31 } 32 }; 33 34 int n; 35 Matrix<int> hf; 36 int lx, ly; 37 38 inline void init(){ 39 readInteger(n); 40 hf = Matrix<int>(n + 1, n + 1); 41 } 42 43 inline void solve(){ 44 memset(hf.p, 0, sizeof(int) * (n + 1) * (n + 1)); 45 hf[1][n / 2 + 1] = 1; 46 lx = 1, ly = n / 2 + 1; 47 for(int k = 2; k <= n * n; k++){ 48 if(lx == 1 && ly != n){ 49 lx = n; 50 ly++; 51 }else if(ly == n && lx != 1){ 52 ly = 1; 53 lx--; 54 }else if(ly == n && lx == 1){ 55 lx++; 56 }else if(hf[lx - 1][ly + 1] == 0){ 57 lx--; 58 ly++; 59 }else{ 60 lx++; 61 } 62 hf[lx][ly] = k; 63 } 64 for(int i = 1; i <= n; i++){ 65 for(int j = 1; j <= n; j++){ 66 printf("%d ", hf[i][j]); 67 } 68 putchar('\n'); 69 } 70 } 71 72 int main(){ 73 freopen("magic.in", "r", stdin); 74 freopen("magic.out", "w", stdout); 75 init(); 76 solve(); 77 return 0; 78 }
直接Tarjan,当然也可以直接用深搜(貌似要比Tarjan快一点,其实思路还是差不多的)
Code(Tarjan)
1 #include<iostream> 2 #include<cstdio> 3 #include<cctype> 4 #include<cstring> 5 #include<map> 6 #include<set> 7 #include<stack> 8 #include<queue> 9 #include<vector> 10 #include<algorithm> 11 using namespace std; 12 typedef bool boolean; 13 template<typename T> 14 inline void readInteger(T& u){ 15 char x; 16 while(!isdigit((x = getchar()))); 17 for(u = x - '0'; isdigit((x = getchar())); u = (u << 3) + (u << 1) + x - '0'); 18 ungetc(x, stdin); 19 } 20 #define smin(a, b) a = min(a, b) 21 22 typedef class Edge{ 23 public: 24 int next; 25 int end; 26 Edge(const int next = 0, const int end = 0):next(next), end(end){} 27 }Edge; 28 29 typedef class MapManager{ 30 public: 31 int *h; 32 Edge *edge; 33 int ce; 34 MapManager():h(NULL), edge(NULL), ce(0){} 35 MapManager(int points, int edges):ce(0){ 36 h = new int[(const int)(points + 1)]; 37 edge = new Edge[(const int)(edges + 1)]; 38 memset(h, 0, sizeof(int) * (points + 1)); 39 } 40 inline void addEdge(int from, int end){ 41 edge[++ce] = Edge(h[from], end); 42 h[from] = ce; 43 } 44 }MapManager; 45 46 #define m_begin(g, i) (g).h[(i)] 47 #define m_next(g, i) (g).edge[(i)].next 48 #define m_end(g, i) (g).edge[(i)].end 49 50 int *uf; 51 int cn; 52 stack<int> s; 53 int *visitID; 54 int *exitID; 55 boolean* visited; 56 boolean* inStack; 57 MapManager g; 58 int result; 59 60 inline void getSonMap(int end){ 61 int counter = 1; 62 int buf = s.top(); 63 int first = buf; 64 s.pop(); 65 inStack[buf] = false; 66 while(buf != end){ 67 buf = s.top(); 68 s.pop(); 69 inStack[buf] = false; 70 uf[buf] = first; 71 counter++; 72 } 73 if(counter > 1) 74 smin(result, counter); 75 } 76 77 void Tarjan(int node){ 78 visitID[node] = exitID[node] = ++cn; 79 visited[node] = true; 80 inStack[node] = true; 81 s.push(node); 82 for(int i = m_begin(g, node); i != 0; i = m_next(g, i)){ 83 int& e = m_end(g, i); 84 if(!visited[e]){ 85 Tarjan(e); 86 exitID[node] = min(exitID[node], exitID[e]); 87 }else if(inStack[e]){ 88 exitID[node] = min(exitID[node], visitID[e]); 89 } 90 } 91 if(exitID[node] == visitID[node]){ 92 getSonMap(node); 93 } 94 } 95 96 int n; 97 98 inline void init(){ 99 readInteger(n); 100 g = MapManager(n, n); 101 uf = new int[(const int)(n + 1)]; 102 visitID = new int[(const int)(n + 1)]; 103 exitID = new int[(const int)(n + 1)]; 104 inStack = new boolean[(const int)(n + 1)]; 105 visited = new boolean[(const int)(n + 1)]; 106 memset(visited, false, sizeof(boolean) * (n + 1)); 107 memset(inStack, false, sizeof(boolean) * (n + 1)); 108 for(int i = 1, a; i <= n; i++){ 109 readInteger(a); 110 uf[i] = i; 111 g.addEdge(i, a); 112 } 113 } 114 115 inline void solve(){ 116 result = 0xfffffff; 117 for(int i = 1; i <= n; i++) 118 if(!visited[i]) 119 Tarjan(i); 120 delete[] visitID; 121 delete[] exitID; 122 printf("%d", result); 123 } 124 125 int main(){ 126 freopen("message.in", "r", stdin); 127 freopen("message.out", "w", stdout); 128 init(); 129 solve(); 130 return 0; 131 }
dfs的话就记一个访问的时间戳,还要即一个是否在栈中,当时间戳不为初值并且在栈中才说明是环
Code(Dfs)
#include<iostream> #include<cstdio> #include<cctype> #include<cstring> #define smin(a, b) a = min(a, b) using namespace std; typedef bool boolean; template<typename T> inline void readInteger(T& u){ char x; while(!isdigit((x = getchar()))); for(u = x - '0'; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - '0'); ungetc(x, stdin); } int n; int timec; int* next; int* rank; boolean* inStack; int result = 0xfffffff; void find(int node){ if(rank[node] != -1 && inStack[node]){ smin(result, ++timec - rank[node]); return; } if(rank[node] != - 1) return; inStack[node] = true; rank[node] = ++timec; find(next[node]); inStack[node] = false; } int main(){ freopen("message.in", "r", stdin); freopen("message.out", "w", stdout); readInteger(n); next = new int[(const int)(n + 1)]; rank = new int[(const int)(n + 1)]; inStack = new boolean[(const int)(n + 1)]; memset(rank, -1, sizeof(int) * (n + 1)); for(int i = 1; i <= n; i++){ readInteger(next[i]); inStack[i] = false; } for(int i = 1; i <= n; i++){ if(rank[i] == -1) find(i); } printf("%d", result); return 0; }
思路很简单,搜!不过如果对子、三带一都去搜的话很耗时间,也很耗代码,而且它们是可以直接算出来的
稍微贪一下心,把能带走的都带走,而且从多的开始带。但是双王要记住特殊处理
搜的内容就只包括顺子,只不过注意所有情况都要搜到,因为某些数据顺子即使搜得长,并不是最优的,反
而导致单牌过多。其他都还是没有什么特别坑的细节。
Code
1 #include<iostream> 2 #include<cstdio> 3 #include<cctype> 4 #include<cstring> 5 #include<map> 6 #include<set> 7 #include<queue> 8 #include<vector> 9 #include<algorithm> 10 #define smin(a, b) a = min(a, b) 11 using namespace std; 12 typedef bool boolean; 13 template<typename T> 14 inline void readInteger(T& u){ 15 char x; 16 while(!isdigit((x = getchar()))); 17 for(u = x - '0'; isdigit((x = getchar())); u = (u << 3) + (u << 1) + x - '0'); 18 ungetc(x, stdin); 19 } 20 21 int n; 22 int kase; 23 int key[14] = {0, 12, 13, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; 24 int had[16]; 25 26 inline void init(){ 27 memset(had, 0, sizeof(had)); 28 for(int i = 1, a, b; i <= n; i++){ 29 readInteger(a); 30 readInteger(b); 31 if(a == 0) had[13 + b]++; 32 else had[key[a]]++; 33 } 34 } 35 36 int calc(){ 37 int counter[5] = {0, 0, 0, 0, 0}; 38 for(int i = 1; i <= 15; i++){ 39 if(had[i] > 0){ 40 counter[had[i]]++; 41 } 42 } 43 int reter = 0; 44 boolean aFlag = 0; 45 if(had[14] == 1 && had[15] == 1){ 46 aFlag = 1; 47 } 48 while(counter[4] && counter[2] >= 2) reter++, counter[4] -= 1, counter[2] -= 2; 49 while(counter[4] && counter[1] >= 2) reter++, counter[4] -= 1, counter[1] -= 2; 50 while(counter[4] && counter[2]) reter++, counter[4] -= 1, counter[2] -= 1; 51 while(counter[3] && counter[2]) reter++, counter[3] -= 1, counter[2] -= 1; 52 while(counter[3] && counter[1]) reter++, counter[3] -= 1, counter[1] -= 1; 53 if(counter[1] >= 2 && aFlag) counter[1] -= 1; 54 return reter + counter[1] + counter[2] + counter[3] + counter[4]; 55 } 56 57 int result; 58 void search(int last, int times){ 59 if(last == 0){ 60 smin(result, times); 61 return; 62 } 63 smin(result, times + calc()); 64 if(times >= result) return; 65 //顺子 66 if(last >= 5){ 67 for(int p = 3; p >= 1; p--){ 68 for(int i = 1; i <= 12; i++){ 69 int k = i; 70 while(had[k] >= p && k < 13) k++; 71 if((k - i) * p >= 5){ 72 for(int j = i; j < k; j++){ 73 had[j] -= p; 74 } 75 for(int j = k - 1; j >= i; j--){ 76 if((j - i + 1) * p >= 5) 77 search(last - (j - i + 1) * p, times + 1); 78 had[j] += p; 79 } 80 } 81 } 82 } 83 } 84 } 85 86 int main(){ 87 freopen("landlords.in", "r", stdin); 88 freopen("landlords.out", "w", stdout); 89 readInteger(kase); 90 readInteger(n); 91 while(kase--){ 92 init(); 93 result = n; 94 search(n, 0); 95 printf("%d\n", result); 96 } 97 return 0; 98 }