题意:
输入一个n行m列的数据库(1<=n<=10000, 1<=m<=10),是否存在两个不同行r1,r2和两个不同列c1,c2,使得这两行和这两列相同,(即(r1,c1)和(r2,c1)相同,(r1,c2)和(r2,c2)相同)。
3 3
How to compete in ACM ICPC,Peter,peter@neerc.ifmo.ru
How to win ACM ICPC,Michael,michael@neerc.ifmo.ru
Notes from ACM ICPC champion,Michael,michael@neerc.ifmo.ru
2 3
1,Peter,peter@neerc.ifmo.ru
2,Michael,michael@neerc.ifmo.ru
NO
2 3
2 3
YES
枚举c1和c2,然后从上到下扫描各行。每次碰到一个新的行r,把c1,c2两列的内容作为一个二元组存到一个map中。如果map的键值中已经存在这个二元组,该二元组映射到的就是所要求的r1,而当前行就是r2。说起来很绕口,其实实现起来还是很简单的。
#include <map>
#include <cstdio>
#include <string>
#include <iostream>
using namespace std;
int m, n;
string s;
map<string, int> mat;
int num[10010][15];
int main() {
while(~scanf("%d%d",&m,&n)) {
cin.get();//cin.get()是保留回车在输入流队列中.而cin是丢弃回车的.
int cnt = 0;
for(int i = 0; i < m; i++) {
getline(cin, s);//可以接收空格
int st = 0; //从第一个字符开始
int en = s.find(',',0);//找到第一个','的位置
for(int j = 0; j < n; j++) {
if(j == n-1) {//当遍历到最后一个字符串
string s1( s.begin() + st, s.end());
if(mat.count(s1)) num[i][j] = mat[s1];
else num[i][j] = (mat[s1] = cnt++);
}
else {
string s1 (s.begin() + st, s.begin() + en);//找字符串
st = en + 1;//从此时逗号后面开始找
en = s.find(',', st);//从st开始找到下一个逗号的位置
if(mat.count(s1)) num[i][j] = mat[s1];
else num[i][j] = (mat[s1] = cnt++);
}
}
}
bool flag = true;
for(int i = 0; i < m-1; i++) {
for(int j = i+1; j < m; j++) {
int p = 0;
int put[2];
for(int k = 0; k < n; k++) {
if(num[i][k] == num[j][k]) {
put[p++] = k;
if(p == 2 && flag) {
printf("NO\n");
printf("%d %d\n",i+1, j+1);
printf("%d %d\n",put[0] + 1, put[1] + 1);
flag = false;
break;
}
}
}
if(!flag) break;
}
if(!flag) break;
}
if(flag) printf("YES\n");
}
return 0;
}