调题小记#01

题目链接-打字练习

先把代码挂出来吧

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>

using namespace std;

int tim;
int rightn = 0;
int kpm;
char s1[10001][1001];   //s1为模板
char s2[10001][1001];   //s2是那家伙打的
int cnt[1001];          //每行字符计数
//先行内后行数
char tmp[10001];
int ptr;
int arr;
//1为模板,2为那家伙打的

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    //读入模板
    ptr = 1;
    while(true){
    cin.getline(tmp, 10001);
        if(strlen(tmp) == 3 && tmp[0] == 'E' && tmp[1] == 'O' && tmp[2] == 'F'){
            break;
        }
        else {
            cnt[ptr] = strlen(tmp);
            arr = 1;
            for(int i = 0; i < strlen(tmp); i++){
                if(tmp[i] == '<' && arr != 1){
                    arr--;
                    cnt[ptr] -= 2;
                }
                else{
                    s1[arr][ptr] = tmp[i];
                    arr++;
            }
        }
            ptr++;
        }
    }
    int n = ptr - 1; // n为输入行数

    //读入那家伙打的
    ptr = 1;
    while(true){
    cin.getline(tmp, 10001);
        if(strlen(tmp) == 3 && tmp[0] == 'E' && tmp[1] == 'O' && tmp[2] == 'F'){
            break;
        }
        else{
            arr = 1;
            for(int i = 0; i < strlen(tmp); i++){
                if(tmp[i] == '<' && arr != 1){
                    arr--;
                }
            else{
                s2[arr][ptr] = tmp[i];
                arr++;
            } 
        }
            ptr++;
        }
        
    }

    //比较
    for(int k = 1; k <= n; k++){
        for(int i = 1; i <= cnt[k]; i++){
            if (s1[i][k] == s2[i][k])   rightn++;
        }
    }
    cin >> tim;
    kpm = rightn * 60 / tim;
    cout << round(kpm);
    return 0;
}

正如最顶部注释,这玩意只能拿50分(其实是40分,估计读入优化太差了而TLE了一个懒得调了)。

其实,这段代码已经经过了3次重构。第一次,用的栈,发现比较不会写(写了两次都炸了);第二次,回忆起双端队列,时间复杂度是开了O2也救不回来的那种。

现在是第三次,发现#6~#10总是wa,且都是比答案少1,怀疑是四舍五入写挂了,但是用了STL也是一样。

经过我2个小时的瞎猜苦心构造,终于发现"x<x<<x"型能使程序结果出错(没加特判,使得"<<"处会有一个<进入字符串)

原因?看到上面那个if了吗?

if(tmp[i] == '<' && arr != 1){
                    arr--;
                    cnt[ptr] -= 2;
                }
                else{
                    s1[arr][ptr] = tmp[i];
                    arr++;

如果此时arr已经为1,就会直接执行else{}中的代码,使得<跑到字符串里。

如何解决?加个特判试试?

f(tmp[i] == '<' && arr != 1){
                    arr--;
                    cnt[ptr] -= 2;
                }
                else if(tmp[i] == '<' && arr == 1){
                    continue;
                }
                else{
                    s1[arr][ptr] = tmp[i];
                    arr++;

目前来看,能解决待判文本中“x<x<<x”的问题,答案中的尚未解决。

2024.7.17留。

2024.7.18Update:睡醒之后清醒多了,发现处理答案时犯了低级错误:没有考虑到"<"并不是一个实体字符(仅限题目中),而strlen()会返回包含"<"数目的字符串长度。
弄完这个就90分了,剩下一个超时的点(无语,开了O2还变成RE)实在不想弄了,弄它得把整个输入部分用getchar()重写一遍不想写了属于是。

这么调一圈下来,这道题是我调试时间第二长的。(最长的是回文质数,当时调了整整3个月)

posted @ 2025-04-17 10:51  林石Linstone  阅读(10)  评论(0)    收藏  举报