IT民工
加油!

今天做的是山东第一届省赛,题目比昨天的容易,但是还是出了五道题,难道难题都只能叫大叔来做?

A: Phone Number

给出N个字符串,判断是否存在一个字符串是另一个字符串的前缀,之前做过一道类似的题,字典树判断前缀确实很方便。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

typedef struct
{
    int next[10];
    int alr, end;
}Trie;

Trie t[110000];
int tp, n;

int insert(char *x, int site)
{
    if(t[site].end)
        return 1;
    if(*x)
    {
        t[site].alr = 1;
        if(!t[site].next[*x - '0'])
            t[site].next[*x - '0'] = tp ++;
        insert(x + 1, t[site].next[*x - '0']);
    }
    else
    {
        t[site].end = 1;
        return t[site].alr;
    }
}

int main()
{
    int T, flag;
    char s[11];
    while( scanf("%d", &n), n )
    {
        tp = 1;
        flag = 0;
        while(n --)
        {
            scanf("%s", s);
            if(!flag && insert(s, 0))
                flag = 1;
        }
        if(flag)
            printf("NO\n");
        else
            printf("YES\n");
        memset(t, 0, sizeof(Trie) * (tp + 1));
    }
    return 0;
}

B: Balloons

这也是一道水题,简单的搜索,分别按照4个方向和八个方向找联通块的数目,然后输出这两种方式得到的结果,隽遒学弟敲的也很快,

也按照题目要求在每个样例之后输出了换行,结果PC^2返回了WA,我们把代码打印出来了,我帮他看了半天也没发现哪有错。后面

老大说试着样例之间输出换行就过了。

# include <cstdio>
# include <cstring>
int n;

bool m[103][103];
bool f[103][103];

const int go[4][2] = {0,1, 1,0, 0,-1, -1,0}; //注意判断是否越界

const int ju[8][2] = {0,1, 1,0, 0,-1, -1,0, -1,1, 1,1, 1,-1, -1,-1};

void f1(int x, int y)
{
    int xx, yy, i;
    f[x][y] = 1;
    for ( i = 0; i < 4; ++i )
    {
        xx = x + go[i][0];
        yy = y + go[i][1];
        if ( xx < 1 || xx > n || yy < 1 || yy > n || !m[xx][yy] || f[xx][yy] ) continue;
        f1(xx, yy);
    }
}

void f2(int x, int y)
{
    int xx, yy, i;
    f[x][y] = 1;
    for ( i = 0; i < 8; ++i )
    {
        xx = x + ju[i][0];
        yy = y + ju[i][1];
        if ( xx < 1 || xx > n || yy < 1 || yy > n || !m[xx][yy] || f[xx][yy] ) continue;
        f2(xx, yy);
    }
}

int t = 0;
int main()
{
    int i, j;
    char s[107];
    while ( scanf("%d", &n) != EOF )
    {
        ++t;

        if ( n == 0 ) break;
        for ( i = 1; i <= n; ++i )
        {
            scanf("%s", s+1);
            for ( j = 1; j <= n; ++j )
                if ( s[j] == '0' ) m[i][j] = 0;
                else m[i][j] = 1;
        }
        int ans1 = 0, ans2 = 0;
        memset(f, 0, sizeof(f));
        for ( i = 1; i <= n; ++i )
            for ( j = 1; j <= n; ++j )
                if ( m[i][j] && ! f[i][j] )
                {
                    ++ans1;
                    f1(i, j);
                }
        memset(f, 0, sizeof(f));
        for ( i = 1; i <= n; ++i )
            for ( j = 1; j <= n; ++j )
                if ( m[i][j] && ! f[i][j] )
                {
                    ++ans2;
                    f2(i, j);
                }
        if ( t > 1 ) printf("\n");
        printf("Case %d: %d %d\n", t, ans1, ans2);
    }
    return 0;
}

C: Clockwise

看了题解是计算几何 + DP,不会,先放着。

D: Shopping

最水的一道题,结果又给我碰上了,输出给定序列最大值 - 最小值的结果的两倍。当时为了敲起来简单,还排序了...

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;
const int MAXN = 100010;
int a[MAXN];

int main()
{
    int n;
    while(scanf("%d", &n), n)
    {
        for(int i = 0; i < n; i ++)
        {
            scanf("%d", &a[i]);
        }
        sort(a, a + n);
        printf("%d\n", (a[n - 1] - a[0]) * 2);
    }
    return 0;
}

E: Emergency

这题是我敲的,之前做过几乎一模一样的题。给出一个图,N个点,M条有向边,Q次操作,M和Q都是10万,N是300,现在假设所有的点都被破坏了,有两

种操作,0 x,修复x结点,意味着我们可以从一个点到另一个点经过x结点。如果x结点已经被修复,则输出一句话。1 x y,输出从x到y的经过修复好的点

的最短路长度,如果x或者y依然是破坏状态也是输出一句话,否则则看最短路是否存在,存在就输出值。一个变化的floyd就可以搞定,每次修复一个点就把

这个点当成k,做k为中间点,任意两点间的最短路。

#include <stdio.h>
#include <string.h>
#include <string.h>

const int MAXN = 350;
const int INF = 0x3f3f3f3f;
int d[MAXN][MAXN];
bool rec[MAXN];
int N, M, Q;

void ReadGraph()
{
    int x, y, z;
    for(int i = 0; i < N; i ++)
        for(int j = 0; j < N; j ++)
        {
            if(i == j) d[i][j] = 0;
            else d[i][j] = INF;
        }
    memset(rec, false, sizeof rec);
    while(M --)
    {
        scanf("%d%d%d", &x, &y, &z);
        if(d[x][y] > z)
            d[x][y] = z;
    }
}

void query()
{
    int op, x, y;
    while(Q --)
    {
        scanf("%d", &op);
        if(0 == op)
        {
            scanf("%d", &x);
            if(rec[x])
                printf("City %d is already recaptured.\n", x);
            if(!rec[x])
            {
                rec[x] = true;
                for(int i = 0; i < N; i ++)
                    for(int j = 0; j < N; j ++)
                    {
                        if(d[i][j] > d[i][x] + d[x][j])
                            d[i][j] = d[i][x] + d[x][j];
                    }
            }
        }
        if(1 == op)
        {
            scanf("%d%d", &x, &y);
            if(rec[x] && rec[y])
            {
                if(d[x][y] < INF)
                    printf("%d\n", d[x][y]);
                else
                    printf("No such path.\n");
            }
            else
            {
                printf("City %d or %d is not available.\n", x, y);
            }
        }
    }
}

int main()
{
    freopen("emergency.in", "r", stdin);
    freopen("Edata.txt", "w", stdout);
    int t = 1;
    while(scanf("%d%d%d", &N, &M, &Q), N + M + Q)
    {
        ReadGraph();
        if(t > 1) printf("\n");
        printf("Case %d:\n", t ++);
        query();
        //printf("\n");
    }
    return 0;
}

F:Fairy tale

模拟题,比赛时隽遒学弟在敲,当时没出,结束后交题过了。

# include <cstdio>
# include <cstring>
# define rep(x) for ( x = 1; x <= n; ++x )
const int go[4][2] = {0,1, 0,-1, 1,0, -1,0}; //E,W,S,N
const int pgo[4][2] = {0,1, 0,-1, -1,0, 1,0}; //E,W,N,S prefer!

const int inf = 2147483647;
int n;
int m[35][35];
bool f[31][31][31][31][4];
bool circle;

int x, y, tx, ty, time;

int abs(int x) { return x > 0 ? x: -x; }
int sqr(int x) { return x * x; }

bool inside(int x, int y)
{ return (x > 0 && x <= n && y > 0 && y <= n); }

bool better(int x, int y, int xx,int yy)
{ return sqr(x-tx)+sqr(y-ty) < sqr(xx-tx)+sqr(yy-ty); }

void Init()
{
    int i,j,k,l,p;
    char s[35];
    rep(i) rep(j) rep(k) rep(l)
        for (p = 0; p < 4; ++p )
            f[i][j][k][l][p] = false;
    rep(i)
    {
        scanf("%s", s+1);
        rep(j)
            if ( s[j] == 'E' ) m[i][j] = 0;
            else if ( s[j] == 'W' ) m[i][j] = 1;
            else if ( s[j] == 'S' ) m[i][j] = 2;
            else if ( s[j] == 'N' ) m[i][j] = 3;
    }
    x = y = 1;
    tx = ty = n;
    time = 0;
    circle = false;
}

int cnt = 0;
int sec[103][5];
bool check()
{
    int i;
    for ( i = 1; i < time; ++i )
        if ( sec[i][0] == x && sec[i][1] == y && sec[i][2] == tx && sec[i][3] == ty && sec[i][4] == (time&3) )
        {
            circle = true;
            return true;
        }
    sec[i][0] = x,sec[i][1] = y,sec[i][2]= tx, sec[i][3] = ty, sec[i][4]= (time&3);
    return false;
}

bool step()
{
    int f1 = (m[x][y]+time)&3, f2 = (m[tx][ty]+time)&3;
    if ( x == tx && y == ty ) return true;
    if ( check() ) return false;
    int xx = x + go[f1][0];
    int yy = y + go[f1][1];
    if ( inside(xx,yy) ) x = xx, y = yy; //自动走
    xx = x, yy = y;
    for ( int i = 0; i < 4; ++i ) //喜好行走
    {
        if ( !inside(x + pgo[i][0], y + pgo[i][1]) ) continue;
        if ( better(x + pgo[i][0],y + pgo[i][1], xx, yy) )
            xx = x + pgo[i][0], yy = y + pgo[i][1];
    }
    x = xx, y = yy;
    int txx = tx + go[f2][0];
    int tyy = ty + go[f2][1];
    if ( inside(txx, tyy) ) tx = txx, ty = tyy; //宝藏走
    ++time;
    return false;
}

int main()
{
    int t = 0;
    while ( scanf("%d", &n), n )
    {
        if ( ++t > 1 ) printf("\n");
        Init();
        printf("Case %d:\n", t);
        while ( time < 100 )
        {
            if ( step() )
            {
                printf("Get the treasure! At step %d.\n", time);
                break;
            }
            if ( circle )
            {
                printf("Impossible. At step %d.\n", time);
                break;
            }
            if ( time == 99 ) printf("Not sure.\n");
        }
    }
    return 0;
}

 

G:Greatest Number

二分

H:Hello World!

一道水题,比赛的时候我和陈兴想多了,但还好陈兴用强大的STL功底过了。给出n个点x和y的值,找到每个点的行和列都比它大的点,优先选择行小的

作为结果,行相等则选择列小的。n^2可以暴力过。

我的代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

const int MAXN = 1 << 10;
const int INF = 0x3f3f3f3f;
int x[MAXN], y[MAXN];
int n;
int main()
{
    //freopen("hello.in", "r", stdin);
    //freopen("hello1.out", "w", stdout);
    int t = 1;
    while(scanf("%d", &n), n)
    {
        for(int i = 1; i <= n; i ++)
        {
            scanf("%d%d", &x[i], &y[i]);
        }
        if(t > 1) printf("\n");
        printf("Case %d:\n", t ++);
        int minx, miny;
        for(int i = 1; i <= n; i ++)
        {
            minx = miny = INF;
            for(int j = 1; j <= n; j ++)
            {
                if(i == j) continue;
                if(y[j] > y[i] && x[j] > x[i])
                {
                    if(minx > x[j])
                    {
                        minx = x[j], miny = y[j];
                    }
                    if(minx == x[j])
                    {
                        if(miny > y[j])
                        {
                            minx = x[j], miny = y[j];
                        }
                    }
                }
            }
            if(minx < INF && miny < INF)
            {
                printf("%d %d\n", minx, miny);
            }
            else
            {
                puts("-1 -1");
            }
        }
    }
    return 0;
}

陈兴的代码:

#include<cstdio>
#include<set>
#include<iterator>
#include<algorithm>
using namespace std;
const int MAXN = 1010;
struct Node
{
    int row, colum;
    int order;
    bool operator<(const struct Node ans) const
    {
        return (row < ans.row || (row == ans.row && colum < ans.colum));
    }
}node[MAXN];
struct Res
{
    int row, colum;
}resl[MAXN];
int n;
set<struct Node> myset;
bool cmp1(const struct Node ans1, const struct Node ans2)
{
    return ans1.row > ans2.row;
}
bool cmp2(const struct Node ans1, const struct Node ans2)
{
    return ans1.order < ans2.order;
}
void Init()
{
    for(int i = 0; i < n; i++)
    {
        scanf("%d%d", &node[i].row, &node[i].colum);
        node[i].order = i;
    }
    sort(node, node + n, cmp1);//行升序
}
void Solve()
{
    int tmp;
    myset.clear();
    for(int i = 0; i < n; i++)
    {
        tmp = node[i].order;
        resl[tmp].row = -1;
        resl[tmp].colum = -1;
        set<struct Node>::iterator it = myset.begin();
        while(it != myset.end())
        {
            if(it->row > node[i].row && it->colum > node[i].colum)
            {
                resl[tmp].row = it->row;
                resl[tmp].colum = it->colum;
                break;
            }
            it++;
        }
        myset.insert(node[i]);
    }
}
int main()
{
    int i = 1;
    while(scanf("%d", &n)!= EOF && n)
    {
        Init();
        Solve();
        if(i > 1) putchar('\n');
        printf("Case %d:\n", i++);
        for(int j = 0; j < n; j++)
        {
            printf("%d %d\n", resl[j].row, resl[j].colum);
        }
    }
    return 0;
}

I:Ivan comes again!

线段树离散化+set。

赛后殷神犇告诉我这道题我做过,我还不信,结果翻到了HDU 3627的代码,拍了下数据,0行差异,我只能表示呵呵。才多久就忘了做过这题...

/*Accepted    3627    1203MS    6848K    2698 B    C++*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int MAXN = 200010;
struct TPoint{
    int x, y, flag;
}pre[MAXN], ans[MAXN], s;

char op[10];
int n, m;

struct Segtree
{
    int l, r, maxy;
}tree[MAXN << 2];

bool cmp(TPoint a, TPoint b)
{
    return a.x < b.x || ( a.x == b.x && a.y < b.y);
}

void build( int rt, int l, int r)
{
    tree[rt].l = l, tree[rt].r = r, tree[rt].maxy = -1;
    if( l == r) return;
    int m = (l + r) >> 1;
    build( rt << 1, l, m);
    build( rt << 1 | 1, m + 1, r);
}

int BS( TPoint nd, int l, int r)
{
    while( l <= r){
        int m = (l + r) >> 1;
        if( nd.x == ans[m].x && nd.y == ans[m].y) return m;
        if( nd.x < ans[m].x || nd.x == ans[m].x && nd.y < ans[m].y)
            r = m - 1;
        else l = m + 1;
    }
    return -1;
}

void update( int rt, int l, int flag)
{
    if( tree[rt].l == l && tree[rt].r == l)
    {
        if( 1 == flag)
            tree[rt].maxy = ans[l].y;
        if( 2 == flag)
            tree[rt].maxy = -1;
        return;
    }
    int m = (tree[rt].l + tree[rt].r) >> 1;
    if(l <= m) update( rt << 1, l, flag);
    else update( rt << 1 | 1, l, flag);
    tree[rt].maxy = max( tree[rt << 1].maxy, tree[rt << 1 | 1].maxy);
}

void query(int rt, TPoint nd)
{
    if(tree[rt].maxy <= nd.y) return;
    if(ans[tree[rt].r].x <= nd.x) return;
    if( tree[rt].l == tree[rt].r){
        s = ans[tree[rt].l]; return;
    }
    query(rt << 1, nd);
    if(s.x == -1) query(rt << 1 | 1, nd);
}

void prepare()
{
    int i;
    for( i = 1, m = 0; i <= n; i ++)
    {
        scanf( "%s%d%d", op, &pre[i].x, &pre[i].y);
        if('a' == op[0]) {
            pre[i].flag = 1;
            ans[++ m] = pre[i];
        }
        else if( 'r' == op[0]) pre[i].flag = 2;
        else pre[i].flag = 3;
    }
    sort( ans + 1, ans + m + 1, cmp);
    build( 1, 1, m);
}

void operation()
{
    for( int i = 1; i <= n; i ++)
    {
        int cnt = BS(pre[i], 1, m);
        if( 3 == pre[i].flag)
        {
            s.x = s.y = -1;
            query( 1, pre[i]);
            if( s.x == -1) printf( "-1\n");
            else printf( "%d %d\n", s.x, s.y);
        }
        else{
            update( 1, cnt, pre[i].flag);
        }
    }
}

int main()
{
    //freopen("Ivan.in", "r", stdin);
    //freopen("Ii.out", "w", stdout);
    int cas = 0;
    while( scanf( "%d", &n), n)
    {
        if( cas ++) printf( "\n");
        printf( "Case %d:\n", cas);
        prepare();
        operation();
    }
    return 0;
}

 

J:Jerry Mouse

题目很长,当时没看,后面大神们说是并查集,其他队都在比赛中A掉了。

posted on 2012-10-03 16:56  找回失去的  阅读(193)  评论(0编辑  收藏  举报