UVA1592解题报告

这道题让我费了我好几天的时间,差不多打掉了我对算法的全部信心。不过,幸好,经过几天的努力我终于AC了这道题,解开了我的一个大心结。

下面我将列出三份代码,其中后两份是WA代码用来给同样WA的同伴提供点思路,看看是否犯了同样的错误。

首先给出的是AC代码,思路如下

将题目抽象知,给出一个M行N列的数据库,要求给出是否存在两行有两列相同。

由于字符串的操作过于繁琐容易超限,所以先进行编号。

编完号后我们手中的表就剩下一串数字,接下来就是对这一串数据的操作。要求是两行的两列相同,所以我们可以枚举所有列的组合并从上往下扫描各行。

AC代码 Time 1.7s

#include<cstdio>
#include<string>
#include<map>
#include<cstring>
#include<sstream>
#include<iostream>
using namespace std;

int row,col,ans,ok;
const int maxn=100;
char table[maxn];
int code[10010][15];
int a,b,c,d;

typedef pair<int,int> P;

map<string,int> id;

void convert(int r)
{
    int c=1;
    string s="";
    for(int i=0;i<=strlen(table);i++)
    {
        char p=table[i];
        if(p==',' || p=='\0')
        {
            if(id.count(s)) code[r][c]=id[s];
            else { id[s]=ans; code[r][c]=ans++; }
            c++; s="";
        }
        else s+=p;
    }
}

void judge()
{
        for(int c1=1;c1<=col;c1++)
        {
            for(int c2=c1+1;c2<=col;c2++)
            {
                map<P,int> m;
                for(int r=1;r<=row;r++)
                {
                    P p=make_pair(code[r][c1],code[r][c2]);
                    if(m.count(p)) { ok=1; a=m[p]; b=r; c=c1; d=c2; return; }
                    else m[p]=r;
                }
            }
        }
}

int main()
{
    while(scanf("%d %d",&row,&col)==2)
    {
        getchar(); ok=ans=0; id.clear();
        memset(code,-1,sizeof(code));
        for(int r=1;r<=row;r++)
        {
            gets(table);
            convert(r);
        }
        judge();
        if(ok)
        {
            printf("NO\n");
            printf("%d %d\n",a,b);
            printf("%d %d\n",c,d);
        }
        else printf("YES\n");
    }
    return 0;
}

错误算法:

没有编号,从上到下扫描行,如果有两列相同的则ok=1,退出

代码如下

#include<cstdio>
#include<string>
#include<map>
#include<cstring>
#include<iostream>
using namespace std;

const int maxn=100;
char table[maxn];
int row,col;
int ok;
int r1,r2,c[2];

void judge(int r,map<string,int> *m)
{
    int cnt=0;
    int ans=0;
    string s="";
    for(int i=0;i<=strlen(table);i++)
    {
        if(table[i]==',' || table[i]=='\0')
        {
            if(m[cnt].count(s)) { r1=m[cnt][s]+1; r2=r+1; c[ans++]=cnt+1; cnt++;  }
            else { m[cnt][s]=r; cnt++;  }
            s="";
        }
        else
        {
            s+=table[i];
        }
    }
    if(ans==2) ok=1;
}

int main()
{
    while(scanf("%d %d",&row,&col)==2)
    {
       ok=0;
       getchar();
       map<string,int> m[10];
       for(int r=0;r<row;r++)
       {
           gets(table);
           if(ok) continue;
           judge(r,m);
       }
       if(!ok) printf("YES\n");
       else
       {
           printf("NO\n");
           printf("%d %d\n",r1,r2);
           printf("%d %d\n",c[0],c[1]);
       }
    }
    return 0;
}


错误原因:当两行有1列相同时m[s]的值是谁呢?而且最后的R值实际取决于最后的映射

错误数据

3 3

1,2,3

4,5,3

6,5,3

正确输出:

NO
2 3
2 3

第二种错误算法,和AC代码差不多,只是扫描时不一样,具体如下

#include<cstdio>
#include<string>
#include<map>
#include<cstring>
#include<sstream>
#include<iostream>
using namespace std;

int row,col,ans,ok;
const int maxn=100;
char table[maxn];
int code[10010][15];
int a,b,c,d;

typedef pair<int,int> P;

map<string,int> id;
map<P,int> m;

void convert(int r)
{
    int c=1;
    string s="";
    for(int i=0;i<=strlen(table);i++)
    {
        char p=table[i];
        if(p==',' || p=='\0')
        {
            if(id.count(s)) code[r][c]=id[s];
            else { id[s]=ans; code[r][c]=ans++; }
            c++; s="";
        }
        else s+=p;
    }
}

void judge()
{
    for(int r=1;r<=row;r++)
    {
       for(int c1=1;c1<=col;c1++)
        {
            for(int c2=c1+1;c2<=col;c2++)
            {
                    P p=make_pair(code[r][c1],code[r][c2]);
                    if(m.count(p)) { ok=1; a=m[p]; b=r; c=c1; d=c2; return; }
                    else m[p]=r;
            }
        }
    }
}

int main()
{
    while(scanf("%d %d",&row,&col)==2)
    {
        getchar(); ok=ans=0; id.clear();
        memset(code,-1,sizeof(code));
        for(int r=1;r<=row;r++)
        {
            gets(table);
            convert(r);
        }
        m.clear();
        judge();
        if(ok)
        {
            printf("NO\n");
            printf("%d %d\n",a,b);
            printf("%d %d\n",c,d);
        }
        else printf("YES\n");
    }
    return 0;
}


错误原因:不能确定是不是两列

错误数据:

2 3

1,2,3

1,3,5

正确答案:YES


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值