Database UVA

对于每组数据,首先通过一个map将每个字符串由一个数字代替,相同的字符串由相同数字代替,不同的字符串由不同数字代替。那么题目就变为了询问是否存在行r1,r2以及列c1,c2使得str[r1][c1]=str[r2][c1]且str[r1][c2]=str[r2][c2](此时所有单元格内都是数字,str[i][j]表示第i行第j列的数字)。也就是寻找两行和两列,它们相交所在的四个单元格中上面的两个与下面两个分别相等。

然后,由于行多列少,可以枚举列。对于每次枚举出的两列c1,c2,先清空map,然后从上往下扫描行。设当前扫描到的行是第k行,则建立二元组(str[k][c1],str[k][c2]),如果map中没有此二元组则将其放入map,并将值设为k;如果map中有此二元组,则表示前面有某行的c1,c2两列与这一行的c1,c2两列分别相同,那么由存入map的方法可知map[二元组]得到"某行",显然r1就是"某行",r2就是k,c1,c2就是枚举出的c1,c2。

#include<vector>
#include<map>
#include<string>
#include<iostream>
using namespace std;
int n,m;
int str[10001][11];
typedef pair<int,int> P;
int now;
map<string,int> IDcache;//根据字符串取ID
map<P,int> m2;//存储由二元组映射到行号
void getstring(string& s)
{
	s="";
	int a=getchar();
	while(a=='
')	a=getchar();
	while(a!='
'&&a!=',')
	{
		s+=(char)a;
		a=getchar();
	}
}
int main()
{
	string s1;
	P p1;
	int i,j,k;
	bool flag;
	while(cin>>n>>m)
	{
		flag=false;
		now=0;
		IDcache.clear();
		for(i=1;i<=n;i++)
			for(j=1;j<=m;j++)
			{
				getstring(s1);
				if(IDcache.count(s1)==1)
					str[i][j]=IDcache[s1];
				else
				{
					IDcache[s1]=(++now);
					str[i][j]=now;
				}
			}
//		for(i=1;i<=n;i++)
//			for(j=1;j<=m;j++)
//				cout<<str[i][j]<<'
';
		for(i=1;i<m;i++)
			for(j=i+1;j<=m;j++)
			{
				m2.clear();
				for(k=1;k<=n;k++)
				{
					//goto不应该乱用,但是跳出很多重循环可以用以简化程序
					//https://baike.baidu.com/item/goto%E8%AF%AD%E5%8F%A5
					p1=P(str[k][i],str[k][j]);
					if(m2.count(p1)==1)
					{
						flag=true;
						cout<<"NO
";
						cout<<m2[p1]<<' '<<k<<'
';
						cout<<i<<' '<<j<<'
';
						goto lab;
					}
					else
						m2[p1]=k;
				}
			}
		lab:
		if(flag==false)
			cout<<"YES
";
	}
	return 0;
}
原文地址:https://www.cnblogs.com/hehe54321/p/8470440.html