Game with Pearls 2014上海全国邀请赛 hdu5090 贪心,匹配

2014上海全国邀请赛

A题——Game with Pearls

hdu5090

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5090

Game with Pearls

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 3672    Accepted Submission(s): 1287


 

Problem Description

Tom and Jerry are playing a game with tubes and pearls. The rule of the game is:

1) Tom and Jerry come up together with a number K.

2) Tom provides N tubes. Within each tube, there are several pearls. The number of pearls in each tube is at least 1 and at most N.

3) Jerry puts some more pearls into each tube. The number of pearls put into each tube has to be either 0 or a positive multiple of K. After that Jerry organizes these tubes in the order that the first tube has exact one pearl, the 2nd tube has exact 2 pearls, …, the Nth tube has exact N pearls.

4) If Jerry succeeds, he wins the game, otherwise Tom wins.

Write a program to determine who wins the game according to a given N, K and initial number of pearls in each tube. If Tom wins the game, output “Tom”, otherwise, output “Jerry”.

Input

The first line contains an integer M (M<=500), then M games follow. For each game, the first line contains 2 integers, N and K (1 <= N <= 100, 1 <= K <= N), and the second line contains N integers presenting the number of pearls in each tube.

Output

For each game, output a line containing either “Tom” or “Jerry”.

Sample Input

2 5 1 1 2 3 4 5 6 2 1 2 3 4 5 5

Sample Output

Jerry

Tom

大意:有n堆石子,你可以给每一堆添加石子。给定一个数字k,要求你给每堆石子添加的个数必须是k个。你可以给每一堆石子交换顺序,最后让第i堆石子里有i个石子,也就是最后石子数量应该是 1,2,3,4,···,n。

这道题我一开始就是想得贪心。排一遍顺序然后从小到大来看是否第i堆是有i个石头,数据很小,时间完全过得去。但是这么做的话会出现一个问题,也就是说,会不会出现原本在前面的匹配到后面了呢??(其实这个时候想到了匹配)于是这个方法不可以,因为顺序不能拍一遍顺序就确定,那么正解来了 就是每次给符合条件的加k,然后每次加k后排序。

之所以wa了一发是因为少了一个=。。。锋锋出了个一个石头的样例,错,然后我改过来了。。。哭唧唧菜的一批我。。。

#include<iostream>
#include<algorithm>
#include<cstdio>

using namespace std;

int a[110];

int main(){
	int T;
	scanf("%d",&T);
	int n,k;
	while(T--){
		scanf("%d%d",&n,&k);
		for(int i = 0;i < n;i++){
			scanf("%d",&a[i]);
		}
		sort(a,a + n);
		int index = 0;
		int book = 0;
		while(index < n){
			while(a[index] == index + 1&&index < n){
				index++;
			}
			if(index >= n){
				break;
			}
			if(a[index] > index + 1){
				book = 1;
				break;
			}
			a[index] = a[index] + k;
			sort(a,a + n);
		}
		if(book == 1){
			printf("Tom\n");
		}
		else{
			printf("Jerry\n");
		}
	}
	return 0;
}

好的这是贪心算法。

接下来用匹配写。由于起始状态和末状态是一一对应的,但是每个起始状态结点能到达的末状态结点不唯一,也就是看最后最大能匹配多少个。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>

using namespace std;

int T,n,k;
int nx,ny;
const int MAXN = 110;
vector<int> V[MAXN];
int a[MAXN];
bool visit[MAXN];
int xmatch[MAXN];
int ymatch[MAXN];

//	Ñ°ÕÒÔö¹ã·¾­
int findpath(int u){
	int i,j;
	for(int i = 0;i < V[u].size();i++){
		j = V[u][i];
		if(visit[j])
			continue;
		visit[j] = 1;
		if(ymatch[j] == -1||findpath(ymatch[j])){
			ymatch[j] = u;
			xmatch[u] = j;
			return 1;
		}
	}
	return 0;
}

//Çó×î´óÆ¥Åä
int maxmatch(){
	int res = 0;
	memset(xmatch,-1,sizeof(xmatch));
	memset(ymatch,-1,sizeof(ymatch));
	
	for(int i = 1;i <= nx;i++){//ʯͷ´Ó1¿ªÊ¼ 
		if(xmatch[i] == -1){
			memset(visit,0,sizeof(visit));
			res += findpath(i);
		}
	}
	
	return res;
} 
 
int main(){
	scanf("%d",&T);
	while(T--){
		scanf("%d%d",&n,&k);
		nx = ny = n;
		for(int i = 1;i <= n;i++){
			scanf("%d",a + i);
			V[i].clear();
		}
		for(int i = 1;i <= n;i++){
			for(int j = 1;j <= n;j++){
				if(i >= a[j]&&(i - a[j])%k == 0)
					V[j].push_back(i); 
			}
		}
		
		if(maxmatch() == n)
			cout << "Jerry" << endl;
		else
		    cout << "Tom" << endl;
		
		
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37136305/article/details/81079277
今日推荐