题目大意:
m个玩家,每个人n张牌,(2 <= m <= 20, 1 <= n <= 50)牌点为1-m*n这m*n个数字,每一轮里,m个玩家各出示一张牌,牌点数最大的赢得这一墩,n轮下来赢得墩数最多的为赢家( m = 4, n = 13时和桥牌的规则一样)给定自己的n张牌,算一下至少能赢得多少墩
样例:
2 5 1 7 2 10 9 6 11 62 63 54 66 65 61 57 56 50 53 48 0 0
分析:
以第一组样例为例:
牌点数为1-10,这样10和9一定能赢,而7则不一定(因为8在别人手里)
同理对于第二组样例:
66,65一定能赢,但63不一定(因为64在别人手里)
但63,62,61里至少可以赢得两墩(因为这三张牌所在的三轮比赛至多输一轮)
这样,可以对m*n张牌点记一个状态,(所有牌点初始化为0,然后自己有的牌点初始化为1)
从m*n向1遍历,若这样牌为自己所有,那么就赢得一墩;若状态为0,那么赢者不确定,但为了取得最大的墩数,对于不确定的,用余下的最小的牌来应对(这张牌点的状态标记为2)
当自己的所有牌都出完后,总墩数即为最大的墩数
代码如下:
#include<iostream>
#include<cstdio>
#include<string.h>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int maxcard = 1010;
const int maxindividual = 55;
int cardstatus[maxcard];
int mycard[maxindividual];
int n,m;
int main(){
int i,j,sum,Case = 0;
while(scanf("%d%d",&m,&n)!=EOF){
sum = 0;
memset(cardstatus,0,sizeof(cardstatus));
if(m == 0 && n == 0)
break;
for(i = 0; i < n; ++i){
scanf("%d",mycard+i);
cardstatus[mycard[i]] = 1;
}
sort(mycard,mycard+n);
for(i = m * n,j = n - 1; j >= 0; --i){
if(cardstatus[i] == 1){
++sum;
--j;
}
else if(cardstatus[i] == 0){
cardstatus[mycard[j]] = 2;
--j;
}
}
printf("Case %d: %d\n",++Case,sum);
}
return 0;
}