poj-1026

7 篇文章 0 订阅
//188K  110MS   C++
#include <cstring>
#include <cstdio>
#include <iostream>

using namespace std;

char str1[205];
char str2[205];

int key[205];

int cycleLength[205];

// void replace(char * str, int keyLength, int strLength) {
//     memset(str2, 0, sizeof(str2));
//     for (int i = 0; i < keyLength; i++) {
//         int pos = key[i] - 1;
//         if (str[i] == 0 || str[i] == '\n') {
//             str2[pos] = ' ';
//         } else {
//             str2[pos] = str[i];
//         }
//     }
//     memcpy(str1, str2, sizeof(str1));
// }

// void solve(char * str, int keyLength, int repeatTime) {
//     // printf("%s\n", str);
//     int strLength = strlen(str);
//     for (int i = 1; i <= repeatTime; i++) {
//         replace(str, keyLength, strLength);
//     }
//     str[keyLength] = 0;
//     printf("%s\n", str);
// }

void getCycleLength(int * key, int keyLength) {
    for (int i = 1; i <= keyLength; i++) {
        int curCycleLength = 0;
        int nextPos = key[i-1];
        while(nextPos != i) {
            curCycleLength++;
            nextPos = key[nextPos-1];
        }
        // printf("%d %d\n", i, curCycleLength + 1);
        cycleLength[i-1] = curCycleLength + 1;
    }
}

// int move(int curPos) {
//     return key[curPos-1];
// }

int moveWithRepeatTime(int beginPos, int repeatTime) {
    if (repeatTime ==0) {
        return beginPos;
    }

    int curPos = beginPos;
    for (int i = 1; i <= repeatTime; i++) {
        curPos = key[curPos-1];
    }
    return curPos;
}

int main() {
    while(1) {
        int keyLength;
        memset(key, 0, sizeof(key));
        scanf("%d", &keyLength);

        if (keyLength == 0) {
            return 0;
        }

        for (int i = 0; i < keyLength; i++) {
            scanf("%d", &key[i]);
        }

        getCycleLength(key, keyLength);

        int repeatTime;
        while (1) {
            scanf("%d", &repeatTime);
            if (repeatTime == 0) {
                break;
            }
            char c;
            scanf("%c", &c);
            memset(str1, 0, sizeof(str1));
            // scanf("%9[^\n]", str1);
            
            for(int i = 0; i < keyLength; i++){
                str1[i] = ' ';
            }
            for(int i = 0; i < keyLength; i++){
                scanf("%c", &c);
                if(c == '\n'){
                    break;
                }
                str1[i] = c;
            }

            int length = strlen(str1);

            memset(str2, ' ', sizeof(str2));
            for (int i = 0; i < keyLength; i++) {
                int curRepeatTime = repeatTime%cycleLength[i];
                int newPos = moveWithRepeatTime(i+1, curRepeatTime);
                // printf("%d -> %d\n", i, newPos - 1);
                if (str1[i] == 0 || str1[i] == '\n') {
                    str2[newPos-1] = ' ';
                } else {
                    str2[newPos-1] = str1[i];
                }
            }
            str2[keyLength]= 0;
            printf("%s\n", str2);
        }
         printf("\n");
    }
}


原理上很简单,就是单纯的模拟,从一个位置移动到另一个位置,

但是题目会要求移动非常多的次数(上万),因此如果搞朴素的模拟,必然TLE。

因此,就要分析一下位移的规律了,对于长度为L的位移数组,最多经过L次,就可以移回原位,这样就算移动N次(N非常大),只需N%移动循环的次数就可以得到一个相对很小的移动次数,就不会TLE了。对每个位置都求解得到其位移循环的最大次数C,然后对每个位置模拟移动N%C次即可,

比如例子中的位移数组:

10
4 5 3 7 2 8 1 6 10 9

对于位置1的数: 1 ->4 -> 7 -> 1 循环最大次数是3

对于位置2的数:2->5->2 循环最大次数是2

对于位置3的数: 3->3, 1

............


该题还考空格输入, 用 scanf("%9[^\n]", str1);一直TLE,怀疑是某次输入被阻塞了,后来不得已一个一个字母的读取了。

最后还要注意,每个block要输出一个空行, 因为这个PE了几次....

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值