1592:Database

45 篇文章 0 订阅
27 篇文章 0 订阅

Database


思路:只枚举c1和c2,然后从上到下扫描各行。每次碰到一个新的行r,把c1,c2两列的内容作为一个二元组存到一个map中。如果map的键值中已经存在这个二元组,该二元组映射到的就是所要求的r1,而当前行就是r2。在主循环之前先做一个预处理——给所有字符串分配一个编号,则整个数据库中每个单元格都变成了整数,上述二元组就变成了两个整数,这个操作同样用到了map。

version 1(1440ms):

#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 10000 + 5,maxm = 10 + 5;
typedef pair<int,int> P;
int m,n,table[maxn][maxm];
string readstr(){
    string s;
    s.resize(20); //一定要sesize 不然会报错 原因暂时不清楚 反正感觉就不太对。。。最低是20
    int cnt = 0;
    char c;
    for(;;){
        c = getchar();
        if(c != '\n' && c != '\r') break;
    }
    for(;;){
        if(c == ',' || c == '\n') break;
        s[cnt++] = c;
        c = getchar();
    }
    return s;
}
int main(){
    while(scanf("%d %d",&n,&m) == 2){
        memset(table,0,sizeof(table));
        map<string,int>snum;
        int cnt = 0;
        for(int i = 1;i <= n;i++){
            for(int j = 1;j <= m;j++){
                string s = readstr();
                if(!snum.count(s)) snum[s] = ++cnt;
                table[i][j] = snum[s];
            }
        }
        int mark = 0;
        for(int c1 = 1;c1 <= m;c1++){
            for(int c2 = c1+1;c2 <= m;c2++){
                map<P,int>record;
                for(int r = 1;r <= n;r++){
                    P t = make_pair(table[r][c1],table[r][c2]);
                    if(record.count(t)){
                         printf("NO\n%d %d\n%d %d\n",record[t],r,c1,c2);
                         mark = 1;
                         break;
                    }
                    record[t] = r;
                }
                if(mark) break;
            }
            if(mark) break;
        }
        if(!mark) printf("YES\n");
    }
    return 0;
}

version 2(1470ms,使用getline读取):

#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 10000 + 5,maxm = 10 + 5;
typedef pair<int,int> P;
int m,n,table[maxn][maxm];
int main(){
    while(scanf("%d %d",&n,&m) == 2){
        getchar(); //一定要记得把这个换行符吃掉
        memset(table,0,sizeof(table));
        map<string,int>ID;
        int cnt = 0;
        string t,s;
        for(int i = 1;i <= n;i++){
            getline(cin,t);
            int lastp = -1;
            for(int j = 1;j <= m;j++){
                int p = t.find(',',lastp+1);
                if(p == string::npos) p = t.length();
                s = t.substr(lastp+1,p-lastp-1);
                if(!ID.count(s)) ID[s] = ++cnt;
                table[i][j] = ID[s];
                lastp = p;
            }
        }
        int mark = 0;
        for(int c1 = 1;c1 <= m && !mark;c1++){
            for(int c2 = c1+1;c2 <= m && !mark;c2++){
                map<P,int>record;
                for(int r = 1;r <= n;r++){
                    P t = make_pair(table[r][c1],table[r][c2]);
                    if(record.count(t)){
                         printf("NO\n%d %d\n%d %d\n",record[t],r,c1,c2);
                         mark = 1;
                         break;
                    }
                    record[t] = r;
                }
            }
        }
        if(!mark) printf("YES\n");
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值