Hoodlum1980 (fafa)'s Technological Blog

Languages mainly using and digging: C / CPP, ASM, C#, Python. Other languages:Java.

博客园 首页 新随笔 联系 订阅 管理

    地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3603

    题意:背景是手机游戏,给出一些字母猜单词。现在假设你猜不出,然后不停重新开始游戏,游戏就每次给你12个大写字母,由于正确字母以外的候选字母是随机给出的,所以两次游戏中发生改变的字母肯定不是答案,是可以去掉的。现在假设你试验了 N 次,给你每次得到的 12 个候选字母。要求按照字母顺序把去掉不可能的字符之后剩下的那些字符输出。

 

    分析:一个比较简单的题目。但是题目描述中没有交代相同的字符是否可能出现多次,但是显然这是可能的。因为一个单词中可以出现重复字符,例如 see ,choose 等。所以如果你假定每个字符只有一个的话肯定 WA,所以这题有很大的 WA比例。只要你知道每个字符是可重复的,这个题目的求解就很简单了。就好比给你一串数字,输出其中最小的一个数字的问题相似,线性时间搞定。

 

    字符候选是一个集合(由0到多个A~Z字符组成),我们假设初始集合是多个 A,多个 B,。。。多个 Z 组成,用 unsigned char flags[26] 来标记它们,flags [ i ] 表示的是字母('A' + i )的个数,把它初始化为一个明显很大的数字,255 就够了。然后对每一次游戏给出的 12 个候选字母,我们取它和现有的集合的交集。最后剩下的集合就是答案。

 

zoj3603_code
#define min(a,b) ((a)<(b)? (a):(b))

#include <stdio.h>
#include <string.h>
int main(int argc, char* argv[])
{
    char line[16];
    unsigned char flags[26], tmp[26];
    int T, N;
    int i, j, k;

    scanf("%ld", &T);
    for(i = 0; i < T; i++)
    {
        memset(flags, 0xff, sizeof(flags));
        scanf("%d\n", &N);
        for(j = 0; j < N; j++)
        {
            gets(line);
            memset(tmp, 0, sizeof(tmp));
            for(k = 0; k < 12; k++)
            {
                tmp[line[k] - 'A']++;
            }
            for(k = 0; k < 26; k++)
            {
                if(flags[k] > tmp[k])
                    flags[k] = tmp[k];
            }
        }
        for(k = 0; k < 26; k++)
        {
            while(flags[k] > 0)
            {
                putchar('A' + k);
                --flags[k];
            }
        }
        printf("\n");
    }
    return 0;
}

 

posted on 2012-06-14 07:39  hoodlum1980  阅读(908)  评论(0编辑  收藏  举报