• 第二章 POJ 基本算法


    基本算法

     

    C++的标准模版库的应用

    poj3096,poj3007

    较为复杂的模拟题的训练

    poj3393,poj1472,poj1027,poj3371,poj2706

     POJ 3096

    水题,map,set随便搞

    POJ 1472

    TLE了一下午,PE了一晚上。。。我滴神啊!

    算时间复杂度,用堆模拟。。。参考的代码。。。T_T

    View Code
    #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月开始往后推的。详见代码:

    View Code
    #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。当然,每一行后边是没有空格的。

    View Code
    #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掉。。。

    View Code
    //#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;
    }
  • 相关阅读:
    Java虚拟机
    Java集合常见面试题一
    5个新自动化测试框架,你值得了解
    Mock工具介绍
    空降,如何做好管理?
    QA在业务变动中如何维护测试用例?
    接口越权扫描平台初探
    程序员删代码泄愤,被判刑5个月,网友:年轻人不讲武德?!
    哪些 Python 库让你相见恨晚?
    两篇毕业论文致谢同一个女朋友?哈哈哈哈!
  • 原文地址:https://www.cnblogs.com/vongang/p/2442500.html
Copyright © 2020-2023  润新知