第二章 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;
}

 

 

 

 

 

 

 

 

posted @ 2012-04-11 15:52  AC_Von  阅读(367)  评论(0编辑  收藏  举报