紫书刷题

**

紫书刷题Day1(共勉)

**(第五章起步)

Uva1592(VJ)
题目大意
给出nm的表格,判断是否存在两行,他们对应存在两列相同元素,即(r1,c1)=(r2,c1);(r1,c2)=(r2,c2)
主要思路
暴力枚举的话O(n^4)会TLE,所以不可以暴力枚举。
这题的思路是选取两列再从第一行开始从上往下扫,记录每一行不同列,最后查找是否有相同的行。时间复杂度O(m
n*logm)。
具体思路
首先就是紫书前面集合栈所提到的ID分配,这里ID分配可以起到很好的作用对于不同的字符串。

int getID(string x){//给每个字符串分配一个id;
    if(id.count(x)){
        return id[x];
    }else{
        id[x]=cnt++;
        return id[x];
    }
}

其次就是对数据的储存,选择用vector的二维数组储存。

vector<int> table[10005];
table[i].push_back(getID(s1));

然后就是储存字符串后对遍历时每一行的储存,由于是一行的两列,故这里可以用到pair来储存两列的id然后用map->行。

map<pair<int,int>,int> pos;//记录每个点对应的id构成的坐标->行数;

最后就是一个字符串的处理了,由于输入的字符串是一行且由","隔开,故此处需要分隔字符串,这里我从大佬那里学到了字符串流的方法来分割,即getline()的用法,详情见代码。

getline(cin,s);stringstream ss(s);
           while(getline(ss,s1,',')){
               table[i].push_back(getID(s1));
           }

需要注意的是上面的方法用到了getline那么就需要getchar()来吃掉回车,这也是初始化的好习惯。
废话不说了上代码(菜菜勿喷)

#include<bits/stdc++.h>
using namespace std;
int n, m;
string s, st;
map<string, int> idmp; // 字符串->id
int getId(string s) { // 获取字符串id,若已存在,直接返回,否则分配id
    if (idmp.find(s) == idmp.end()) idmp.insert({s, idmp.size()}); // 不存在
    return idmp[s];
}
int main() {
    while (cin >>n >>m) {
        getchar(); vector<int> table[n+1]; idmp.clear(); // 初始化!!!
        for (int i = 0; i < n; i ++) {
            getline(cin, s); stringstream input(s);
            while (getline(input, st, ',')) table[i].push_back(getId(st));
        }
        bool isPNF = true; // 标记是否为PNF
        for (int i = 0; i < m-1 && isPNF; i ++) { // 遍历任意两列
            for (int j = i+1; j < m && isPNF; j ++) {
                map<pair<int,int>, int> pos; // 两列对应字符串标号->行
                for (int k = 0; k < n && isPNF; k ++) { // 每一行
                    if (pos.find({table[k][i],table[k][j]}) == pos.end()) {
                        pos[{table[k][i],table[k][j]}] = k;
                    }
                    else {
                        printf("NO\n%d %d\n%d %d\n", pos[{table[k][i],table[k][j]}]+1, k+1, i+1, j+1);
                        isPNF = false;
                    }
                }
            }
        }
        if (isPNF) printf("YES\n");
    }
    return 0;
}

有无大佬可以看一下下面的码错在哪了

#include<bits/stdc++.h>
using namespace std;
map<string,int> id;
vector<int> table[10005];
int cnt=0;//用于记录已经有多少个不同的字符串了;
int getID(string x){//给每个字符串分配一个id;
    if(id.count(x)){
        return id[x];
    }else{
        id[x]=cnt++;
        return id[x];
    }
}
void solve(int n,int m){
    for(int i=0;i<m;i++){
        for(int j=m-1;j>i;j--){
            map<pair<int,int>,int> pos;//记录每个点对应的id构成的坐标->行数;
            for(int k=0;k<n;k++){
                if(pos.count({table[k][i],table[k][j]})){
                    cout<<"NO"<<endl;
                    cout<<pos[{table[k][i],table[k][j]}]+1<<k+1<<endl;
                    cout<<i+1<<j+1<<endl;
                    return;
                }else{
                    pos[{table[k][i],table[k][j]}]=k;
                }
            }
        }
    }
    cout<<"YES"<<endl;
    return;
}
int main(){
   string s,s1;
   int n,m;
   while(cin>>n>>m){
       getchar();id.clear();cnt=0;table[10005].clear();//初始化
       for(int i=0;i<n;i++){
           getline(cin,s);stringstream ss(s);
           while(getline(ss,s1,',')){
               table[i].push_back(getID(s1));
           }
       }
       solve(n,m);
   }
   system("pause");
   return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值