UVa - 1592 Database(STL综合,强推!)
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=51293
#include <iostream> #include <map> #include <vector> #include <string> #include <cstdio> #include <cstring> #define MAXN 10005 #define MAXM 15 using namespace std; /************************************************************************************************************* 题意: 给一个数据库,查找是否存在(r1,c1)=(r2,c1) && (r1,c2)=(r2,c2),即:不同的二行,对应二列字符串相同 解题: 1. 首先读入字符串,将每个字符串分配一个编号,这样在遍历数据库查找时会迅速很多,不用比较字符串比如对于 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 编号为 0 1 2 3 4 5 6 4 5 2. 因为要找到两对相同的列,四重遍历可以找到,但是太慢了,考虑将c1,c2两列的内容一起存到map中, 所以map的key为(x,y)【x,y分别代表对应字符串的编号】,map的值为对应的行r1,遍历行就是r2; 所以三重遍历即可完成。 注意: 1. 注意要找到的二列,不一定相邻,可以相隔; 2. 对于map<node,int> data; data.clear()的位置要放对,每次遍历完2列, 就要清空一次(因为要找到对应两行两列(r1,c1)=(r2,c1) && (r1,c2)=(r2,c2) ) 编程思路分三步 1,读入数据做映射 2,遍历行,进行判断 3,释放相关空间 未完待续...... 1,operator的实现原理 2,map<Node,int,cmp> table_num的实现原理 *************************************************************************************************************/ struct Node { int x,y; }; struct cmp { bool operator() (const Node X,const Node Y) const{ if(X.x != Y.x) return X.x<Y.x; if(X.y != Y.y) return X.y<Y.y; return false; } }; map<string,int> IDcache; vector<string> IDcard; //终于体会到这个有什么用了,类似不定长数组,用来从小到大给map映射的string赋值id //具体见函数 fuc,这个函数在处理这种题很有用!!! char temp[MAXN][100]; //gets(temp[i])来读入每行信息,总共MAXN行信息。gets可以读入空格,较为方便 int table[MAXN][MAXM]; //表格行列,值表示该行列的 string在map映射下的 ID int fuc(string x) { if(IDcache.count(x)) return IDcache[x]; IDcard.push_back(x); return IDcache[x]=IDcard.size()-1; } int main() { int n,m; while(cin>>n>>m) { //读入datebase信息并作映射,将映射的ID(int),存入table[MAXN][MAXM]中 getchar(); for(int i = 1;i <= n;i ++) gets(temp[i]); string s_temp; for(int i = 1;i <= n;i ++){ int cnt=1; for(int j = 0;j <= strlen(temp[i]);j ++){ if(temp[i][j] == ',' || j == strlen(temp[i])){ //每列之间有逗号,作为列判断依据 table[i][cnt++]=fuc(s_temp); //行数 : i 列数 : cnt s_temp.clear(); //存完一次清空临时 s_temp } else s_temp+=temp[i][j]; //临时存储每列的字符串信息 } } //三重循环,两重循环来遍历列。将两列之间的信息(即ID)映射到 map<Node,int,cmp> table_num中 //第三重循环来遍历不同行 int flag=0; for(int i = 1;i < m;i ++){ for(int j = i+1;j <= m;j ++){ map<Node,int,cmp> table_num; //在这里定义,实现了注意的第二点,每次重新录入数据并作映射 for(int k = 1;k <= n;k ++){ Node p; p.x=table[k][i]; p.y=table[k][j]; if(!table_num.count(p)) table_num.insert(pair<Node,int> (p, k)); //类似于将两列信息作为整体Node,映射到cmp else{ cout<<"NO"<<endl; cout<<table_num[p]<<" "<<k<<endl; cout<<i<<" "<<j<<endl; flag=1; break; } } if(flag) break; } if(flag) break; } if(!flag) cout<<"YES"<<endl; //一次处理完datebase记得归还空间 memset(table,0,sizeof(table)); memset(temp,0,sizeof(temp)); s_temp.clear(); IDcache.clear(); IDcard.clear(); } return 0; }