UVa 100|The 3n+1 Problem|暴力|坑点多

31 篇文章 0 订阅

原文地址:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=36

题目翻译

计算机科学的问题经常被划分到已有的确切问题类别上(比如NP,无解,递归等)。本题需要你分析一个未知类别的算法的性质。
考虑这样的一个算法:
1 input n
2 print n
3 if n = 1 then STOP
4   if n is odd then n = 3n + 1
5   else n = n / 2
6 GOTO 2

输入22,算法中的n将会按照以下顺序变化:
22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1

有人认为对于任意输入的正整数,上述算法能在有限步数内结束。尽管算法很简单,但是仍然不知道这个推测是不是正确的。我们已经审查了0~1,000,000内的所有整数满足该推测。

给定n,我们可以知道上面的那个序列的数字个数k(比如n=22,数字的个数是16)。对于任意的两个数i和j,你的任务是找出i和j之间(包括i和j)的某个数,其算法序列数字个数最多,输出这个序列的数字个数。

输入

输入有n组测试数据。每个测试数据一行两个整数i和j( 0<i,j<10,000 )。
你可以假定中间运算结果不会超过32位整数范围。

输出

对于每个测试数据,输出一行3个整数i,j和k。i和j即为输入对应的i和j。

样例输入

1 10
100 200
201 210
900 1000

样例输出

1 10 20
100 200 125
201 210 89
900 1000 174

题解

暴力即可,中间运算显然可以缓存,不过本题数据而言不需要啦。

#include <cstdio>
#include <vector>
#define rep(i,j,k) for(i=j;i<k;++i)
using namespace std;
const int N = 105;
vector<int> piles[N];
int temp[N], temp_cnt = 0;
int pile[N], height[N];

template<class T>
void internal(int from, int h, T callback) {
    while (piles[from].size() >= h) {
        int x = *piles[from].rbegin();
        piles[from].pop_back();
        int pile_id = callback(x);
        piles[pile_id].push_back(x);
        height[x] = piles[pile_id].size();
        pile[x] = pile_id;
    }
}

void restoreBlocks(int from, int h) {
    internal(from, h, [](int x){ return x; });
}

void moveBlocks(int from, int h, int to) {
    internal(from, h, [=](int x){ return to; });
}

int main() {
    int n, from, to, i, t = 0;
    char op[8], prep[8];

    rep(i,0,n) pile[i] = i, height[i] = 1;

    while (scanf("%s%d%s%d", op, &from, prep, &to) == 4
            && op[0] != 'q') {

        if (prep[0] == 'o') // onto
            restoreBlocks(pile[to], height[to]);

        if (op[0] == 'm') // move
            restoreBlocks(pile[from], height[from]);

        moveBlocks(pile[from], height[from], pile[to]);

    }
    rep(i,0,n) {
        printf("%d:", i);
        for (auto element : piles[i])
            printf(" %d", element);
        printf("\n");
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值