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,[email protected]
            How to win ACM ICPC,Michael,[email protected]
            Notes from ACM ICPC champion,Michael,[email protected]
            编号为
            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;
}


你可能感兴趣的:(UVa - 1592 Database(STL综合,强推!))