HDU 6675 度度熊与排列【2019百度之星初赛二1002】

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=6675

 

度度熊与排列

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 472    Accepted Submission(s): 151

Problem Description

度熊有一个机器,这个机器有一个 1∼M 的排列 p[1..M] 当作参数,若丢进一个长度为 M 的字符串,此机器会将此字符串重新排列后再输出,重新排列的方式为:原本第 i 个位置的字符会变到第 p[i] 个位置。

举例来说,当 M=3,p[1]=3,p[2]=1,p[3]=2,那么丢 "abc" 进入这个机器后,机器会输出"bca";若丢进的是 "ded",那么机器会输出 "edd"。

某天,度熊不小心忘记这个机器的参数了,只记得参数的长度是 M,于是他丢了 N 长度为 M 的字符串进去,并记录下对于每个字符串机器的输出结果,请你根据这些结果,帮度熊找回这个机器的参数。若有多组参数都满足度熊的记录,请输出字典序最小的排列作为参数。若并不存在任何参数满足度熊的记录,请输出 −1。

注:对于两个相异的排列a: a[1..M] 和 b[1..M],我们称 a 比 b 小当且仅当 存在一个 i,满足对于所有小于 i 的 j 都有 aj=bj 且 ai<bi。

Input

有多组询问,第一行包含一个正整数 T 代表有几组询问。

每组询问的第一行包含两个正整数 N,M,分别代表度熊丢进机器的字符串数目以及参数的长度。接下来还有 2×N 行,每行有一个长度为 M 的字符串,当中的第 2×i−1 行的字符串代表度熊丢进去机器的第 i 个字符串,而第 2×i 行的字符串代表机器对于第 i 个字符串的输出结果。

* 1≤T≤100

* 1≤N≤20

* 1≤M≤50

* 字符串由英文小写字母('a' 至 'z') 组成

Output

对于每一个询问,输出一行,若不存在任何参数满足度熊的记录,这行只包含一个整数 −1。否则这行包含一个排列,代表此机器所有可能的参数中字典序最小的那个。

Sample Input

4
1 3
abc
bca
2 4
aaab
baaa
cdcc
cccd
3 3
aaa
aaa
bbb
bbb
ccc
ccc
1 1
a
z

Sample Output

3 1 2
2 4 3 1
1 2 3
-1

Note 第一组询问中, $p[1]=3,p[2]=1,p[3]=2$ 是唯一的机器可能的参数。 第二组询问中, $p=[2,4,3,1]$ 和 $p=[3,4,2,1]$ 都是机器可能的参数,不过 $[2,4,3,1]$ 的字典序比 $[3,4,2,1]$ 还小,故必须输出 2,4,3,1。

解题思路:

以上面输出为2431为例

①定义并初始结果集。

vector<int>ret[M];
//  // 初始集合:
//  1 2 3 ... M
//  1 2 3 ... M
//      ...
//  1 2 3 ... M
//  此处 M 等于 4

②输入一组字符(两行),统计字符串中每个位置上的字符可以跳转的位置,存入tmp集合。

vector<int>tmp[M];
//  遍历记下可能位置
//  2 3 4
//  2 3 4
//  2 3 4
//  1

③求 ret与 tmp交集 tmp_ret, 然后ret = tmp_ret 

vector<int>tmp_ret[M];
//  求交集。tmp_ret = ret 交 tmp;
//  更新结果集。 ret = tmp_ret;
//  ret:
//  2 3 4
//  2 3 4
//  2 3 4
//  1

④循环重复②③步骤,得到最终结果集ret。

//  ret:
//  2 3
//  4
//  2 3
//  1

⑤分析ret,贪心,找最小跳转位置,看能否得到ans。

输出时贪心的对于每个位置(1->m),输出它所能跳转的最小位置,如果有一个位置无法跳转的话,那么输出-1

 

ac代码:

#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<vector>
using namespace std;

#define  N  21
#define  M  52

char src[M][N];
char des[M][N];

vector<int>ret[M];

int main()
{
	ios::sync_with_stdio(false);
	int T, n, m;
	cin>>T;
	while(T--){
		memset(src, 0, sizeof(src));
		memset(des, 0, sizeof(des));
		for(int i=0;i<M;i++){
			ret[i].clear();
			for(int j=1;j<=M;j++){
				ret[i].push_back(j);
			} 
		} 	
		cin>>n>>m;
		for(int ii=0;ii<n;ii++){
			cin>>src[ii];
			cin>>des[ii];
			vector<int>tmp[M];
			// 求可能的位置存入tmp 
			for(int j=0;j<m;j++){
				for(int k=0;k<m;k++){
					if(src[ii][j]==des[ii][k]){
						tmp[j].push_back(k+1);
					}
				}
			}
			
			vector<int>tmp_ret[M];
			// 求 ret与 tmp交集 
			for(int i=0;i<m;i++){				
				for(int j=0;j<tmp[i].size();j++){
					int a;
					for(a=0;a<ret[i].size();a++){
						if(ret[i][a]==tmp[i][j]){
							break;
						}
					}
					if(a<ret[i].size()){
						// 找到目标,tmp[i][j]属于交集元素,则存入tmp_ret 
						tmp_ret[i].push_back(tmp[i][j]);
					}
				}
				// 将tmp_ret的结果交给ret 
				ret[i].clear();
				sort(tmp_ret[i].begin(), tmp_ret[i].end());
				for(int j=0;j<tmp_ret[i].size();j++){
					ret[i].push_back(tmp_ret[i][j]);
				}
				tmp_ret[i].clear();	
			}
		}
		
		int vis[m+1];
		memset(vis, 0, sizeof(vis));
		// 求一个可能的组合 
		vector<int>ans; 
		for(int i=0;i<m;i++){
			for(int j=0;j<ret[i].size();j++){
				if(vis[ret[i][j]]==0){
					vis[ret[i][j]]=1;
					ans.push_back(ret[i][j]);
					break;
				}	
			}	
		} 
		if(ans.size()!=m){
			cout<<-1<<endl;
		}
		else{
			for(int index = 0; index < m-1; index++){
				cout<<ans[index]<<" ";
			}
			cout<<ans[m-1]<<endl;
		}

	}	
	return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值