1124 Raffle for Weibo Followers (20 分)
1. 題目
John got a full mark on PAT. He was so happy that he decided to hold a raffle(抽獎) for his followers on Weibo -- that is, he would select winners from every N followers who forwarded his post, and give away gifts. Now you are supposed to help him generate the list of winners.
Input Specification:
Each input file contains one test case. For each case, the first line gives three positive integers M (≤ 1000), N and S, being the total number of forwards, the skip number of winners, and the index of the first winner (the indices start from 1). Then M lines follow, each gives the nickname (a nonempty string of no more than 20 characters, with no white space or return) of a follower who has forwarded John's post.
Note: it is possible that someone would forward more than once, but no one can win more than once. Hence if the current candidate of a winner has won before, we must skip him/her and consider the next one.
Output Specification:
For each case, print the list of winners in the same order as in the input, each nickname occupies a line. If there is no winner yet, print Keep going...
Sample Input 1:
9 3 2
Imgonnawin!
PickMe
PickMeMeMeee
LookHere
Imgonnawin!
TryAgainAgain
TryAgainAgain
Imgonnawin!
TryAgainAgain
Sample Output 1:
PickMe
Imgonnawin!
TryAgainAgain
Sample Input 2:
2 3 5
Imgonnawin!
PickMe
Sample Output 2:
Keep going...
2. 題意
John進行轉發抽獎活動,給出三位正整數M,N,S,分別表示轉發的總人數、小明決定的中獎間隔、以及第一名中獎者的序號(編號從1開始)。每位網友可能多次轉發,但只能中一次獎。如果處於當前位置的網友中過獎,則一直順延到下一位沒有中獎的網友。
3. 思路——模擬+map
- 如果第1位中獎者的序號大於轉發總人數,說明沒人中獎,直接輸出return 0即可。
- 否則從第1位中獎者S開始,每N位產生一名中獎者:如果該名網友先前中獎過,那麼就順延給下一位沒有中獎的網友;否則就輸出該名中獎者的網名,並將其置為中獎過的狀態!
- 錯誤總結:
- 這題我自己因為沒有理解對題目意思,所以卡了很久,剛開始題目有點沒看懂,這是硬傷,後面看了翻譯,又理解錯了題目,以為順延值順延一位,沒有想到順延那一位如果也中獎過再往下順延的情況。綜上理解,導致卡了很久,題目本身並不難。
- 還有就是剛開始想到用set來判斷網友有沒有中獎過,但是這比起使用map麻煩很多,所以選擇正確的資料結構很有必要!
4. 程式碼
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main()
{
int m, n, s;
cin >> m >> n >> s;
map<string, int> res;
string names[m + 1];
for (int i = 1; i <= m; ++i)
cin >> names[i];
if (s > m) // 如果第一位獲勝者的位數大於轉發總數,說明沒有獲勝者
cout << "Keep going..." << endl;
// 從第一位獲勝者s開始,每間隔n位產生一名獲勝者
for (int i = s; i <= m; i += n)
{
if (res[names[i]] == 1) // 如果這位獲勝者已經拿過一次獎了
{
i++; // 那麼開始順延給下一位
while (i <= m) // 一直順延,直到沒有獲獎過之前都沒獲獎過的那一位
{
if (res[names[i]] == 0)
{
cout << names[i] << endl;
res[names[i]] = 1;
break;
}
i++;
}
} else // 如果這位獲勝者未獲過獎,則輸出
{
cout << names[i] << endl;
res[names[i]] = 1;
}
}
return 0;
}