基本算法
|
C++的标准模版库的应用 |
poj3096,poj3007 |
较为复杂的模拟题的训练 |
poj3393,poj1472,poj1027,poj3371,poj2706 |
POJ 3096
水题,map,set随便搞
POJ 1472
TLE了一下午,PE了一晚上。。。我滴神啊!
算时间复杂度,用堆模拟。。。参考的代码。。。T_T
#include <iostream> #include <cstring> #include <cstdio> #include <cstdlib> #include <string> using namespace std; const int N = 20; char str[N*N]; int fac[N], mul[N], stk[N]; //fac存放系数,mul用来算系数等级,stk为元素栈,标记是n还是数字 int Num(char *s) { int i, num = 0, n = strlen(s); for(i = 0; i < n; ++i) { num = num*10 + s[i] - '0'; } return num; } int main() { //freopen("data.in", "r", stdin); int C, cas = 0, top, exp; int i, num; scanf("%d", &C); while(C--) { scanf("%s", str); memset(fac, 0, sizeof(fac)); for(i = 0; i < N; ++i) mul[i] = 1; top = 0; exp = 0; //exp为n的指数 while(~scanf("%s", str)) { if(top == 0 && strcmp(str, "END") == 0) break; if(!strcmp(str, "LOOP")) { scanf("%s", str); if(!strcmp(str, "n")) { stk[++top] = 1; exp++; } else { num = Num(str); stk[++top] = 0; for(i = top; i < N; ++i) { mul[i] *= num; } } } else if(!strcmp(str, "OP")) { scanf("%s", str); num = Num(str); fac[exp] += num*mul[top]; } else { if(stk[top]) exp--; --top; } } printf("Program #%d\nRuntime = ", ++cas); int fs = N; while(fac[fs] == 0 && fs >= 0) --fs; if(fs < 0) printf("0"); else if(fs == 0) printf("%d", fac[fs]); else { for(i = fs; i >= 0; --i) { if(fac[i] == 0) continue; if(i == 0) printf("+%d", fac[i]); else { if(i < fs) printf("+"); if(fac[i] > 1) printf("%d*", fac[i]); printf("n"); if(i > 1) printf("^%d", i); } } } printf("\n\n"); } return 0; }
poj 3393
把题目当小说看了。。。得了个1Y,嘿嘿
大概说下题意吧:Gregorian calendar这种记年法,说的是 <= 1582的年份,x%4 == 0则是润年。> 1582的年份,(x%4 == 0 && x%100 != 0) || x%400 == 0)为润年。特殊的,1700年为润年;1752年9月的月历是这样的:
linux下cal一下就行。
然后规定,一周7天,工作日是1到5,6,7休息。如果一个月第一个工作日是周1,那么这个月就是good,如果一个月最后一个工作日是周5,那么这个月是luck的。
给一个时间段,问这段时间luck月份跟good月份各有多少个。
思路:没推出公式来,暴力打表,从公元1年1月开始往后推的。详见代码:
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <ctime> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define REP(i, n) for((i) = 0; (i) < (n); ++(i)) #define FOR(i, l, h) for((i) = (l); (i) <= (h); ++(i)) #define FORD(i, h, l) for((i) = (h); (i) >= (l); --(i)) #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) x < y ? x : y #define Max(x, y) x < y ? y : x #define E(x) (1 << (x)) const double eps = 1e-8; typedef long long LL; using namespace std; struct month { int swk; //记录一个月开始是星期几 int ewk; //记录一个月结束是星期几 }; struct Year { month M[13]; }; Year y[10010]; int mon[13] = {0, 1, -1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1}; bool isleap(int x) { //判是不是润年 if(x <= 1582 && x%4 == 0) return true; if(x > 1582 && ((x%4 == 0 && x%100 != 0) || x%400 == 0)) return true; return false; } void init() { y[1].M[1].swk = 6; y[1].M[1].ewk = 1; int i, j; for(i = 1; i < 10000; ++i) { for(j = 1; j <= 12; ++j) { if(i == 1 && j == 1) continue; if(i == 1752 && j == 9) { //特殊的,用linux下cal 9 1752看的。。。这算开挂吗? y[i].M[j].swk = 2; y[i].M[j].ewk = 6; continue; } if(j != 1) y[i].M[j].swk = (y[i].M[j-1].ewk + 1)%7; //算月初 else y[i].M[j].swk = (y[i-1].M[12].ewk + 1)%7; if(mon[j] == 0) y[i].M[j].ewk = (y[i].M[j].swk + 30 - 1)%7; //算月末 else if(mon[j] == 1) y[i].M[j].ewk = (y[i].M[j].swk + 31 - 1)%7; else { if(isleap(i) || i == 1700) y[i].M[j].ewk = (y[i].M[j].swk + 29 - 1)%7; else y[i].M[j].ewk = (y[i].M[j].swk + 28 - 1)%7; } } } } int main() { //freopen("data.in", "r", stdin); init(); int n, y1, m1, y2, m2; int lk, gd, i, j; scanf("%d", &n); while(n--) { scanf("%d%d%d%d", &y1, &m1, &y2, &m2); lk = gd = 0; //统计 if(y1 == y2) { for(j = m1; j <= m2; ++j) { if(y[y1].M[j].swk == 6 || y[y1].M[j].swk == 0 || y[y1].M[j].swk == 1) gd++; if(y[y1].M[j].ewk == 6 || y[y1].M[j].ewk == 0 || y[y1].M[j].ewk == 5) lk++; } } else { for(j = m1; j <= 12; ++j) { if(y[y1].M[j].swk == 6 || y[y1].M[j].swk == 0 || y[y1].M[j].swk == 1) gd++; if(y[y1].M[j].ewk == 6 || y[y1].M[j].ewk == 0 || y[y1].M[j].ewk == 5) lk++; } for(i = y1 + 1; i <= y2 - 1; ++i) { for(j = 1; j <= 12; ++j) { if(y[i].M[j].swk == 6 || y[i].M[j].swk == 0 || y[i].M[j].swk == 1) gd++; if(y[i].M[j].ewk == 6 || y[i].M[j].ewk == 0 || y[i].M[j].ewk == 5) lk++; } } for(j = 1; j <= m2; ++j) { if(y[y2].M[j].swk == 6 || y[y2].M[j].swk == 0 || y[y2].M[j].swk == 1) gd++; if(y[y2].M[j].ewk == 6 || y[y2].M[j].ewk == 0 || y[y2].M[j].ewk == 5) lk++; } } printf("%d %d\n", lk, gd); } return 0; }
poj 1027
题意不难,挺有意思的一道模拟题。
大概的分成几个过程:bfs求连通块,删除块,上下调整,左右调整。
wa了十几次,有一个变量忘记初始化了。本机上跑出来的数据和标程给的数据对拍没问题,但交上总是不对。后来加上初始化就过了。。。
注意!别挺discuss里瞎扯淡!按题目要求来就行,空行是between。当然,每一行后边是没有空格的。
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <ctime> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define REP(i, n) for((i) = 0; (i) < (n); ++(i)) #define FOR(i, l, h) for((i) = (l); (i) <= (h); ++(i)) #define FORD(i, h, l) for((i) = (h); (i) >= (l); --(i)) #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) x < y ? x : y #define Max(x, y) x < y ? y : x #define E(x) (1 << (x)) const double eps = 1e-8; typedef long long LL; using namespace std; const int N = 100; struct node { int x; int y; node(int a = 0, int b = 0) : x(a), y(b) {} }; node q[1000000]; int dir[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; bool vis[N][N]; char map[N][N]; char st[N]; int n, m; void display() { int i, j; printf("----------------------------------\n"); for(i = 0; i < n; ++i) { for(j = 0; j < m; ++j) { if(map[i][j] == ' ') printf(" "); else printf("%c", map[i][j]); } cout << endl; } printf("++++++++++++++++++++++++++++++++++\n"); } int bfs(node a) { //求连通块的大小 int l = 0, r = 0; q[r++] = a;; vis[a.x][a.y] = 1; char col = map[a.x][a.y]; int i, xx, yy, ans = 1; node u; while(l < r) { u = q[l++]; for(i = 0; i < 4; ++i) { xx = u.x + dir[i][0]; yy = u.y + dir[i][1]; if(map[xx][yy] == col && !vis[xx][yy] && (xx >= 0 && xx < n && yy >= 0 && yy < m)) { vis[xx][yy] = true; q[r++] = node(xx, yy); ans++; } } } return ans; } void del(node a) { //删除块 int l = 0, r = 0; q[r++] = a; char col = map[a.x][a.y]; int i, xx, yy; node u; map[a.x][a.y] = ' '; while(l < r) { u = q[l++]; for(i = 0; i < 4; ++i) { xx = u.x + dir[i][0]; yy = u.y + dir[i][1]; if(map[xx][yy] == col && (xx >= 0 && xx < n && yy >= 0 && yy < m)) { map[xx][yy] = ' '; q[r++] = node(xx, yy); } } } //display(); } void changeUD() { //上下调整 int i, j, s, k; for(i = n - 1; i >= 0; --i) { for(j = 0; j < m; ++j) { if(map[i][j] == ' ') { s = i; k = i; while(map[s][j] == ' ') --s; for( ; s >= 0; --s) { map[k--][j] = map[s][j]; map[s][j] = ' '; } } } } } void changeLR() { //左右调整,要注意的是,只有满足一个列是空的才将后边的往前移一列。 int i, j, k, s; bool f; for(j = 0; j < m; ++j) { s = j; k = j; f = true; for(s = j; s < m; ++s) { for(i = n - 1; i >= 0; --i) if(map[i][s] != ' ') {f = false; break;} if(!f) break; } if(s == j) continue; for(; s < m; ++s, ++k) { for(i = n-1; i >= 0; --i) { map[i][k] = map[i][s]; map[i][s] = ' '; } } } } void solve() { int Max, Mx, My, t; int i, j, cnt = 0, cas = 0, sum = 0; while(1) { CL(vis, false); Max = 1; for(j = 0; j < m; ++j) { for(i = n-1; i >= 0; --i) { if(map[i][j] == ' ') continue; t = bfs(node(i, j)); if(t > Max) { Max = t; Mx = i; My = j; } } } if(Max < 2) break; printf("Move %d at (%d,%d): removed %d balls of color %c, got %d points.\n", ++cas, n-Mx, My+1, Max, map[Mx][My], (Max - 2)*(Max - 2)); sum += (Max - 2)*(Max - 2); del(node(Mx, My)); changeUD(); //display(); changeLR(); //display(); } for(i = 0; i < n; ++i) { for(j = 0; j < m; ++j) if(map[i][j] != ' ') cnt++; } if(!cnt) sum += 1000; printf("Final score: %d, with %d balls remaining.\n", sum, cnt); } int main() { //freopen("H.7.dat", "r", stdin); //freopen("data.out", "w", stdout); int t, i, cas = 0; n = 10; m = 15; scanf("%d", &t); while(t--) { for(i = 0; i < n; ++i) for(int j = 0; j < m; ++j) map[i][j] = ' '; for(i = 0; i < n; ++i) { scanf("%s", map[i]); } //display(); printf("Game %d:\n\n", ++cas); solve(); if(t) printf("\n"); } return 0; }
update:2012/10/23
POJ 3007
纯枚举,没有任何技巧,不过这提专卡STL,但是刷STL刷的心烦,所以直接跳过了,今天发现这题太无语了。。。
模拟:
POJ 3371
没什么技巧可言,模拟就行,1Y,(explanation points = ‘!’, '?';元音里面居然还有y,上午没发现,郁闷了一上午没过样例),感觉最好还是把所有的字母都换成小写或大写比较好。 不是到有什么trick会让这么多人wa掉。。。
//#pragma comment(linker,"/STACK:327680000,327680000") #include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define REP(i, n) for((i) = 0; (i) < (n); ++(i)) #define FOR(i, l, h) for((i) = (l); (i) <= (h); ++(i)) #define FORD(i, h, l) for((i) = (h); (i) >= (l); --(i)) #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("data.in", "r", stdin) #define Write() freopen("data.out", "w", stdout); const double eps = 1e-8; typedef long long LL; const int inf = ~0u>>2; using namespace std; string str; char to_lower(char x) { if(x >= 'A' && x <= 'Z') return x + 32; else return x; } bool is_syllalbe(char x) { if(x == 'a' || x == 'e' || x == 'i' || x == 'o' || x == 'u' || x == 'y') return true; return false; } bool is_snode(char x) { if(x == ';' || x == ':' || x == '.' || x == '!' || x == '?') return true; return false; } int main() { //Read(); int sentences = 0, words = 0, syllalbes = 0; bool fs; while(cin >> str) { int len = str.size(); fs = false; while(len > 0) { if(is_snode(str[len-1])) {len--; fs = true;} else break; } if(len == 0) continue; if(fs == true) sentences++; words++; if(len <= 3) {syllalbes++; continue;} str[len] = '\0'; for(int i = 0; i < len; ++i) { if( is_syllalbe(to_lower(str[i])) && !is_syllalbe(to_lower(str[i+1])) ) syllalbes++; } if(str[len-1] == 'e' && str[len-2] != 'l') syllalbes--; if(str[len-1] == 'd' && str[len-2] == 'e') syllalbes--; if(str[len-1] == 's' && str[len-2] == 'e') syllalbes--; } //printf("%d %d %d\n", sentences, words, syllalbes); printf("%.2f\n", 206.835 - 1.015*words/(sentences*1.) - 84.6*syllalbes/(words*1.) + eps); return 0; }