【2019.4.5】
这道题看了书上思路才写出来
从uDebug中的测例可以看出,代码是需要按列枚举的:先从第1列和第2列开始,枚举每一行,把这一行的第1列和第2列的元素组成二元组,记录其出现的行数,放到map里,看是否有重复的二元组
如果找到重复二元组,直接跳出所有循环,输出NO
如果没找到,就再枚举第1列和第3列,直到枚举完所有列,输出YES
map的结构:<<二元组>,<行数>>
<二元组>:<i行j列的字符串,i行k列的字符串>
<行数>:<i>
那么现在问题变成了:如何把两个字符串组成二元组放到map的key里?
我们可以分两步来做:
1、首先将一个字符串转化成一个int整数
将【复杂数据类型】转换成【int】的一大方法就是编号(ID),用map<复杂数据类型, int>
来提供一一映射。
比如这道题,是把字符串string转换成int
比如【刘汝佳书】例题5-5 UVA12096这道题,是把集合set转换为int
无外乎就是写一个int getID(string s)
子函数,当map中有s时,返回其ID,没有时,先插入到map中,并根据map.size()返回其ID
2、其次将两个int整数转化成二元组
突然想起来这道电子表格的题【刘汝佳书】例题4-5 UVA512
这道题里面用了一个方法:用一个整数index = i*10000 + j
来表示一个位置的格子(i,j)
其中10000
是个比较大的数字,保证index
不会重复
在本题中,我们也可以用这样的方法,把两个int整数转化成一个整数
本题最多有10000行,10列,10^6个元素
因此,假设两个字符串的序号分别为i
和j
,我们可以用index = i*100000 + j
来表示i
和j
组成的二元组,其中index
为long long
型的
此时,map
结构变成:
map的结构:<long long, int>
long long:第i行中,j列和k列的字符串组成的二元组
int:行数,i
代码如下:
#include <iostream>
#include <map>
#include <string>
#include <vector>
using namespace std;
vector<vector<string>> table; //存表
map<long long, int> mi; //字符串对-行号
map<string, int> ID; //字符串-ID
//获取字符串s的ID
//如果已经在ID表中,返回
//如果没有,分配一个新ID,插入ID表
int getID(string s) {
if(ID.count(s)) return ID[s];
else {
int i=ID.size();
ID[s] = i;
return i;
}
}
int main()
{
//freopen("C:\\Users\\Summer\\Desktop\\input.txt", "r", stdin);
//freopen("C:\\Users\\Summer\\Desktop\\output.txt", "w", stdout);
int n, m;
string s;
char c;
bool isPNF;
while(cin>>n>>m) {
//初始化
table.clear();
mi.clear();
isPNF = true;
//输入
getchar(); //第一行输入最后的换行符
for(int i=0; i<n; i++) {
table.push_back(vector<string>());
for(int j=0; j<m; j++) {
//获取一个格子中的字符串,遇到EOF、逗号、换行停止
s = "";
while((c = getchar())!=EOF && c!=',' && c!='\n') {
s += c;
}
table[i].push_back(s);
}
}
//遍历每两列c1,c2
int r1, r2;
int c1, c2;
for(c1 = 0; c1 < m; c1++) {
for(c2 = c1+1; c2 < m; c2++) {
mi.clear();
//对于每一行i
for(int i=0; i<n; i++) {
//分别获取i行c1列和c2列的字符串ID
int id1 = getID(table[i][c1]);
int id2 = getID(table[i][c2]);
//如果这个二元组已经在表内,证明重复,直接退出
if(mi.count(id1*100000+id2)) {
isPNF = false;
r1 = mi[id1*100000+id2];
r2 = i;
break;
}
//如果二元组不在表内,就插入表内
else{
mi[id1*100000+id2] = i;
}
}
if(!isPNF) break;
}
if(!isPNF) break;
}
//输出
if(!isPNF) {
cout<<"NO"<<endl;
printf("%d %d\n%d %d\n", r1+1, r2+1, c1+1, c2+1);
}
else cout<<"YES"<<endl;
}
return 0;
}