PTA 7-66 秀恩爱分得快 题解

PTA 7-66 秀恩爱分得快 题解

测试点三让我改了两天代码!!!!!
但是最后我还是没能完全确定测试点三是为什么“段错误”
测试点三错误的可能猜测:
可能有一张图片有且仅有一个人,且他(她)是情侣之一

一道模拟题,没什么特别的值得探讨的思维点,需要注意的坑点有:

  • 出现 \(-0\) 的情况如何处理
  • 最后给出情侣时男女方给定顺序不定
  • 如果男女方都不在任一一张图片里边如何处理

直接贴满分屎山代码了:

//cpp
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n, m;
const double eps = 1e-3;
int flag;

struct nodea{
    int id;
    double val;
}na[10010];

bool operator < (nodea x, nodea y){
    if(abs(abs(x. val) - abs(y.val)) < eps) return abs(x.id) < abs(y.id);
    else return x.val > y.val;
}

struct nodeb{
    int id;
    double val;
}nb[10010];

bool operator < (nodeb x, nodeb y){
    if(abs(abs(x. val) - abs(y.val)) < eps) return abs(x.id) < abs(y.id);
    else return x.val > y.val;
}

vector <int> vc[1010];
int a, b;

inline long long read(){
	char readch=getchar(); ll readtmp=0;
	ll readflag=1;
	while(readch<'0' || '9'<readch){if(readch=='-')readflag=-1;readch=getchar();}
	while('0'<=readch && readch<='9'){readtmp=readtmp*10+readch-'0';readch=getchar();}
    if(readflag == -1 && readtmp == 0) return -1010;// 0 -> man
	return readtmp*readflag;
}

bool check(){ // 检查,是否只需要输出(a, b)

    if(na[0].val == 0 && nb[0].val == 0) return 1;// 如果a, b, 都不在任一照片里,那么a, b, 最大亲密值肯定也是0
    
    bool flaga = 0, flagb = 0;

    if(na[0].id == b) flaga = 1; // a的最大亲密对象是b
    if(nb[0].id == a) flagb = 1;

    int x = 0;
    //由于最大值可能会有重复,而operator排序无法保证在前的是情侣对方,我们需要一个个找
    
    while(abs(na[x++].val - na[x].val) < eps){
        if(na[x].id == b) flaga = 1; 
    }

    x = 0;
    while(abs(nb[x++].val - nb[x].val) < eps){
        if(nb[x].id == a) flagb = 1;
    }
    return flaga && flagb;
}



void print_only_ab(){
    if(a == 0){
        if(!flag) printf("-%d %d", a, b);
        else printf("%d -%d", b, a);
    }
    else {
        if(!flag) printf("%d %d", a, b);
        else printf("%d %d", b, a);
    }
}

void printa(){
    int x = 0;

    if(a == 0) printf("-%d %d\n", a, na[0].id);
    else printf("%d %d\n", a, na[0].id);

    while(abs(na[x++].val - na[x].val) < eps){
        if(a == 0) printf("-0 %d\n", na[x].id);
        else printf("%d %d\n", a, na[x].id);
    }
}
void printb(){
    int x = 0;
    if(nb[0].id!=0) printf("%d %d\n", b, nb[0].id);
    else printf("%d -0\n", b);

    while(abs(nb[x++].val - nb[x].val) < eps){
        if(nb[x].id!=0) printf("%d %d\n", b, nb[x].id);
        else printf("%d -0\n", b);
    }
}

void pre(){ // 预处理
    cin >> n >> m;

    for(int k=1; k<=m; k++){
        int x = read();
        for(int i=1; i<=x; i++){
            int y = read();
            vc[k].push_back(y);
        }
    }

    cin >> a >> b;
    if(b < a) {
        swap(a, b); // a->women ; b-> man
        flag = 1;
    }
}

void work(){
    // 记录a, b, 对每一个人的亲密值
    for(int i=1; i<=m; i++){
        int len = vc[i].size();
        if(find(vc[i].begin(), vc[i].end(), a) != vc[i].end()){

            for(int j=0; j < len; j++){
                int x = vc[i][j];
                //如果男方是0,直接记录就行,如果女方是0,那她已经标记为-1010了,不会影响结果统计
                if(x >= 0) {
                    na[x].val += 1.0/len;
                    na[x].id = x;
                }               
                
            }

        }

        if(find(vc[i].begin(), vc[i].end(), b) != vc[i].end()){
            for(int j=0; j< len; j++) {
                int x = vc[i][j];

                if(x < 0 && x!=-1010) {
                    x = abs(x);
                    nb[x].val += 1.0/len;
                    nb[x].id = -1*x;
                }
                else if(x == -1010){
                    nb[0].val += 1.0/len;
                    nb[0].id = 0;
                }

            }
        }

    }
}


int main(){
    
    pre();

    if(a == 0) a = -1010; 
    // 显然我们需要处理 a==-0 的情况,此时 b>0 一定成立,那么 a<b 一定成立。所以不会出现pre()中swap会影响答案的现象
    //于是我们把-0替换为-1010来避免0与-0的混乱
    work();

    sort(na, na+n);
    sort(nb, nb+n);

    if(a == -1010) a=0;

    if(check()){
        print_only_ab();
        return 0;
    }


    if(!flag){
        printa();
        printb();        
    }
    else {
        printb();
        printa();
    }  


    return 0;
}   

反思

对于模拟题,我们需要多采用模块化编称,多组装成接口的形式调用,一个是可以使逻辑明显,一个是可以简化代码,最好是第一遍写的时候就有严谨与模块化的意识,并自大至小,由框架到细节,想清楚再动键盘,一旦写完一遍,后面改起来会非常折磨

posted @ 2024-10-25 15:25  [丘李]Chilllee  阅读(134)  评论(0)    收藏  举报