地址: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;}