WAhaha_hnu (zoj 2010 oct月赛)

官方解题报告 http://blog.watashi.ws/1515/zojmonthly1010/

 

A题  签到题,╮(╯▽╰)╭,因为 int -> char* 错了一次,还是很粗心。

View Code
#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#include<string>



using namespace std;



const int N = 101100;

char str[N];





bool isch( char ch ){

    if( (ch>='a'&&ch<='z') || (ch>='A'&&ch<='Z') )

        return true;

    return false;

}

string get_str( int x ){

    

    string tmp;

    char sa[1010];    

    int len = 0;

    while( x ){

        sa[len++] = x%10 + '0'; x /= 10;

    }

    for(int i = len-1; i >= 0; i-- )

        tmp += sa[i];

    return tmp;

}

int main(){

    while( gets( str) ){

        if( strcmp( str, "EOF" ) == 0 ) break; 



        //printf("str = %s", str );    

        int len = strlen(str), n = 0, i = 0;

        string s;    

        

        while( i < len )    

        {

            if( isch( str[i] ) ){



                s += str[i];



                int t = i+1;

                while( isch(str[t]) && (t<len) ) ++t;

                t--;



                if( t-i >= 1 ){

                    if( t-i >= 2 )    

                        s += get_str( t-i-1 );

                    s += str[t];    

                }    

                i = t+1;    

            }    

            else    s += str[i++];

        }

        printf("%s\n", s.c_str() );    

    }

    return 0;

}

 

B题  一开始理解错题意,粗心一路到底啊~~

  假设横切为x,纵切为y,克隆为a, 则对于总分数n,以及操作次数m,共有

    2*x*(y+1) + a = n

    x + y + a = m 

  两式联立可得 x, y 的计算式, 因为 n,m 都比较大, 但是 x*y <= n => x <= sqrt(n) || y <= sqrt(n)

  所以我们可以通过分别枚举 x,y 到sqrt(n) 来得出结果, 因为 x,y对称,所以可以在一个循环内得出。

  另外,以上两式的成立条件是在 x > 0 的前提下, 所以当 x = 0,时候要特判,还有当 n <= m 时也要特判。

View Code
#include<stdio.h>

#include<stdlib.h>

#include<math.h>

#define MIN(a,b) (a)<(b)?(a):(b)

typedef long long LL;



int main(){



    int n, m, T;

    scanf("%d", &T);



    while( T-- )

    {

        scanf("%d %d", &n,&m);

        if( n <= m ){

            printf("-1\n");

            continue;

        }    

        if( n-1 == m ){

            printf("0\n");

            continue;

        }    

        bool flag = false;

        int res = m+1;

        int Max = sqrt(n)+1;    

        for(int x = 0; x <= Max; x++ )

        {

            int ta = n-m-x, tb = 2*x-1;    

            if( ta%tb == 0 ){

                int y = ta/tb;

                if( (y>=0) && (x+y<=m) ){    

                    flag = true;    

                    res = MIN( res, m-x-y );    

                }    

            }

            ta = n-m+x; tb = 2*x+1;

            if( ta%tb == 0 ){

                int y = ta/tb;

                if( (y >=0) && (x+y<=m) ){

                    flag = true;

                    res = MIN( res, m-x-y);

                }

            }

        }    

        if( flag )  printf("%d\n", res );

        else    printf("-1\n");

    }

    return 0;

}

 

E题 看题后第一眼想到DP, 但是时间复杂度无法承受,然后就没管了,回头细想下,觉得贪心应该还是能过的... 越学越笨了~~~

  题目未限定通过陷阱顺序, 通过将陷阱按照 D 排序后, 依次处理,若累积时间 T <= Di 则拆除过去,否则失血,此时选择 [1,i]区间

中时间消耗最大的,这里使用优先队列 来维护。

View Code
#include<iostream>

#include<cstdio>

#include<cstring> 

#include<queue>

#include<algorithm>

using namespace std;

const int N = 25010;



pair<int,int> p[N];



int n, k;



int main(){

    while( scanf("%d%d", &n,&k) != EOF)

    {

        for(int i = 0; i < n; i++)

            scanf("%d%d", &p[i].second,&p[i].first );

        sort( p, p+n );

        int T = 0, hp = 0;

        priority_queue< int > Q;

        

        for(int i = 0; i < n; i++ ){

            T += p[i].second;

            Q.push( p[i].second );

            while( T > p[i].first ){

                T -= Q.top(); Q.pop();

                hp++;

            }    

        }

        if( hp < k ) printf("%d\n", hp );

        else printf("-1\n");

    }

    return 0;    

}

 

I题 ╮(╯▽╰)╭,比赛时看题能力还是不够,错把题目看成是 折现上的点 相邻的直接距离了。

  计算折线总长度后,得到点间距离,然后从起点开始模拟查找就可以得出结果了。

 

你可能感兴趣的:(ZOJ)