题意:给定N个数,给定一个正整数K,然后要对每个数,要么不增加,要么增加K的正整数倍,然后使得N个数刚好是1~N的一个排列。可以的话输出“Jerry",否则输出”Tom"。
这个题目做法还是挺多的。这里我就直接上最简单粗暴的做法。
由于N最多100,所以构建二分图,左边是原数组,右边是目标数组。然后枚举每个原数和每个目标数,如果通过以上操作可以将原数变成目标数,就连一条边,然后求一下最大匹配,如果最大匹配等于N,说明可以完成,否则失败。
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
int T, n, k, a[110];
vector<int> V[110];
int match[110];
bool vis[110];
bool dfs(int x){
for(int i=0; i<V[x].size(); i++){
int j = V[x][i];
if(vis[j]) continue;
vis[j] = 1;
if(match[j]==-1 || dfs(match[j])){
match[j] = x;
return 1;
}
}
return 0;
}
bool ok(){
memset(match,-1,sizeof(match));
int ans = 0;
for(int i=1; i<=n; i++){
memset(vis, 0, sizeof(vis));
if(dfs(i)) ans++;
}
return ans==n;
}
int main(){
scanf("%d", &T);
for(int t=1; t<=T; t++){
scanf("%d %d", &n, &k);
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);
}
}
puts(ok()?"Jerry":"Tom");
}
return 0;
}