HDU1041——Computer Transformation,HDU1042——N!,HDU1043——Eight

目录

HDU1041——Computer Transformation

题目描述

运行代码

代码思路

HDU1042——N!

题目描述

运行代码

代码思路

HDU1043——Eight

题目描述

运行代码

代码思路

HDU1041——Computer Transformation

题目描述

Problem - 1041

题目翻译
问题描述:最初,计算机中写入了一个由一位数字 1 组成的序列。在每个连续的时间步,计算机同时将每个数字 0 转换为序列 1 0,将每个数字 1 转换为序列 0 1。因此,在第一步之后,得到序列 0 1;在第二步之后,得到序列 1 0 0 1;在第三步之后,得到序列 0 1 1 0 1 0 0 1 等等。要找出经过 n 步后,序列中会出现多少对连续的 0 ?

输入:每一行输入包含一个自然数 n(0 < n ≤ 1000)。

输出:对于每个输入的 n,打印经过 n 步后序列中出现的连续 0 对的数量。

运行代码

#include<iostream>
#include<string>
#include<cmath>
using namespace std;

// 这个函数实现的是两个字符串的加法操作。
string acm(string& co, string& gq) {
    string str, strr;
    int i, j;
    int len_co = co.length();
    int jin = 0, ji = 0, tmp, temp; // 进位标志,结果字符标志

    // 字符串乘法实现,这里实际上是在进行二倍操作,即乘以2。
    for (j = len_co - 1; j >= 0; j--) {
        tmp = ((co[j] - '0') * 2 + jin) % 10;
        jin = (co[j] - '0') * 2 / 10;

        str = char(tmp + '0') + str;
    }
    if (jin) // 如果有进位,则添加到结果字符串最前面。
        str = char(jin + '0') + str;

    // 对齐两个字符串的长度,准备做加法。
    int len_str = str.size();
    int len_gq = gq.size();
    int n = abs(len_str - len_gq);
    if (len_str < len_gq)
        for (i = 0; i < n; i++)
            str = '0' + str;
    else
        for (i = 0; i < n; i++)
            gq = '0' + gq;

    // 字符串加法实现。
    for (i = len_str - 1; i >= 0; i--) {
        temp = str[i] - '0' + gq[i] - '0' + ji;
        ji = temp / 10;
        temp = temp % 10;
        strr = char(temp + '0') + strr;
    }
    if (ji)
        strr = char(ji + '0') + strr;

    return strr;
}

// 主函数开始执行程序。
int main() {
    int n;
    string ls[1001]; // 存储每一步的结果序列。

    // 初始化前两步的序列。
    ls[1] = "0";
    ls[2] = "1";

    // 构建序列,这一步可以保留,但应该使用更有效的方法来计算连续0对。
    for (int i = 3; i <= 1000; i++) {
        ls[i] = acm(ls[i - 2], ls[i - 1]);
    }

    // 修改:读取用户输入并计算连续0对的数量。
    while (cin >> n) {
        const string& seq = ls[n];
        int zeroPairs = 0; // 计算连续0对的数量。

        // 遍历序列,计算连续0对的数量。
        for (size_t i = 1; i < seq.size(); ++i) {
            if (seq[i-1] == '0' && seq[i] == '0') {
                zeroPairs++;
            }
        }

        cout << zeroPairs << endl; // 输出连续0对的数量。
    }

    return 0;
}

代码思路

  1. 初始化: 我们从初始序列 "1" 开始。

  2. 迭代更新序列:

    • 在每一步中,我们将序列中的每一个 0 替换成 1 0,每一个 1 替换成 0 1
    • 这意味着在第 n 步后,序列的长度将是 2^n
  3. 计算连续0对的数量:

    • 在每一步结束时,我们遍历序列,如果遇到连续的 0,则增加计数器。
    • 注意,由于序列的生成规则,连续的 0 只可能出现在替换 0 为 1 0 后的位置上,因此我们只需要在每次替换后检查新生成的 0 是否与下一个字符构成一对连续的 0
  4. 优化: 实际上,我们可以观察到连续0对的数量遵循一个模式,可以通过递推关系直接计算,而不需要实际生成序列。具体地,设 f(n) 是第 n 步后连续0对的数量,那么 f(n) = f(n-1) + f(n-2)。这是因为每次迭代,上一步的所有连续0对都将被保留,同时新的0对将在上上步的基础上产生(因为替换 0 会产生新的 0,而这些新的 0 只可能与紧接着的 0 形成对)。初始条件是 f(1) = 0f(2) = 0

HDU1042——N!

题目描述

Problem - 1042

运行代码

#include <iostream>
#include <cstring>
using namespace std;

int main() {
    int n, i, j, end;
    int a[100000] = { 0 };
    while (cin >> n) {
        memset(a, 0, sizeof(a));
        end = 0;
        a[0] = 1;
        for (i = 1; i <= n; i++) {
            // 模拟乘法运算,每一位都乘以 i
            for (j = 0; j <= end; j++) {
                a[j] = a[j] * i;
            }
            // 进位
            for (j = 0; j <= end; j++) {
                if (a[j] > 10000 && j == end) {
                    int c = a[j] / 10000;
                    a[j] = a[j] % 10000;
                    a[j + 1] += c;
                    end++;
                }
                else if (a[j] > 10000) {
                    int c = a[j] / 10000;
                    a[j] = a[j] % 10000;
                    a[j + 1] += c;
                }
            }
        }
        cout << a[end];
        for (i = end - 1; i >= 0; i--) {
            printf("%04d", a[i]);
        }
        cout << endl;
    }
    return 0;
}

代码思路

  1. 初始化:声明了一个足够大的数组a,可以容纳最多100,000组四位数字。变量end用于追踪数组a中最后使用的索引。

  2. 输入循环:

    • 程序从标准输入读取整数,直到没有更多的输入为止。
    • 对于每次输入的n,使用memset将数组a重置为全零。
  3. 阶乘计算:

    • 一个循环从1n运行,模拟乘法操作,对这个范围内的每个数进行乘法运算。
    • 在循环内部,数组a的每一个元素都被乘以i
    • 乘法后,程序处理大于10,000的数值(因为每个a[j]保存四位数字)的进位操作。如果某个值超过10,000,则除以10,000得到进位(c),余数则存回a[j]。进位加到数组中的下一个位置a[j+1]上,可能因此增加数字的长度,即end的值递增。
  4. 输出:程序以倒序方式打印计算出的阶乘,从最高有效位的四位数字开始。使用%04d格式化字符串来打印每一组四位数字,确保任何不足四位的数字前有补零。

HDU1043——Eight

题目描述

Problem - 1043

运行代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int N = 500005, has[9] = { 1,1,2,6,24,120,720,5040,40320 }, dx[4] = { -3,3,-1,1 };
int v1[N], v2[N];
char a[30], d1[10] = { "udlr" }, d2[10] = { "durl" };
string b = "123456780";
struct qw
{
    int a;
    char ch;
    qw(int A = 0, char C = 0)
    {
        a = A, ch = C;
    }
}pre[N];
struct qwe
{
    int a;
    string c;
    qwe(int A = 0, string C = "")
    {
        a = A, c = C;
    }
}e;
void print(int x)
{
    if (pre[x].a == -1)
        return;
    print(pre[x].a);
    printf("%c", pre[x].ch);
}
int ha(string e)
{
    int s = 0, i, j, k;
    for (i = 0; i < 9; i++)
    {
        k = 0;
        for (j = 0; j < i; j++)
            if (e[j] > e[i])
                k++;
        s += k * has[i];
    }
    return s;
}
int main()
{
    while (gets_s(a))
    {
        int k = 0;
        e.c = "";
        for (int i = 0, j = 0; i < strlen(a); i++)
            if (a[i] != ' ')
            {
                if (a[i] == 'x')
                    e.a = j, e.c += '0';
                else
                    e.c += a[i];
                j++;
            }
        for (int i = 0; i < 9; i++)
            if (e.c[i] != '0')
                for (int j = 0; j < i; j++)
                    if (e.c[j] != '0' && e.c[j] > e.c[i])
                        k++;
        memset(v2, 0, sizeof(v2));
        memset(v1, 0, sizeof(v1));
        if (k & 1)
            printf("unsolvable\n");
        else
        {
            qwe f, g;
            int a = 2;
            queue<qwe>q1, q2;
            v1[ha(e.c)] = 1;
            pre[1].a = -1, pre[2].a = -1;
            f = qwe(8, b);
            v2[ha(f.c)] = 2;
            q1.push(e), q2.push(f);
            while (!q1.empty() && !q2.empty())
            {
                f = q1.front();
                q1.pop();
                int p = ha(f.c);
                if (v2[p])
                {
                    print(v1[p]);
                    for (int k = v2[p]; pre[k].a != -1; k = pre[k].a)
                        printf("%c", pre[k].ch);
                    printf("\n");
                    break;
                }
                for (int i = 0; i < 4; i++)
                    if ((i != 0 || f.a >= 3) && (i != 1 || f.a <= 5) && (i != 2 || f.a % 3 != 0) && (i != 3 || f.a % 3 != 2))
                    {
                        int x = f.a + dx[i];
                        g = f;
                        swap(g.c[f.a], g.c[x]);
                        int q = ha(g.c);
                        if (v1[q])
                            continue;
                        v1[q] = ++a;
                        g.a = x;
                        pre[a] = qw(v1[p], d1[i]);
                        q1.push(g);
                    }
                f = q2.front();
                q2.pop();
                p = ha(f.c);
                if (v1[p])
                {
                    print(v1[p]);
                    for (int k = v2[p]; pre[k].a != -1; k = pre[k].a)
                        printf("%c", pre[k].ch);
                    printf("\n");
                    break;
                }
                for (int i = 0; i < 4; i++)
                    if ((i != 0 || f.a >= 3) && (i != 1 || f.a <= 5) && (i != 2 || f.a % 3 != 0) && (i != 3 || f.a % 3 != 2))
                    {
                        int x = f.a + dx[i];
                        g = f;
                        swap(g.c[f.a], g.c[x]);
                        int q = ha(g.c);
                        if (v2[q])
                            continue;
                        v2[q] = ++a;
                        g.a = x;
                        pre[a] = qw(v2[p], d2[i]);
                        q2.push(g);
                    }
            }
        }
    }
    return 0;
}

代码思路

  1. 数据结构和变量:

    • has[]:一个存储阶乘的数组,用于哈希函数中。
    • dx[]:表示移动空白方块的方向(上、下、左、右)。
    • d1[] 和 d2[]:分别表示第一个和第二个BFS队列的方向字符串。
    • v1[] 和 v2[]:访问数组,用于跟踪第一次和第二次BFS队列中的状态。
    • pre[]:一个数组,用于存储到达特定节点的父节点以及采取的方向。
    • ef 和 g:表示拼图状态及其相关属性的结构体。
  2. 哈希函数(ha):这个函数根据每个方块的位置为给定的拼图状态计算一个哈希值。它使用的是逆序对的数量(相对于最终位置错乱的方块)乘以距离末尾位置的距离的阶乘。

  3. 主要逻辑:

    • 读取输入字符串,得到拼图的初始配置。
    • 判断拼图是否可解,通过计算初始状态下方块的逆序对数量。如果逆序对的数量是奇数,那么拼图无解。
    • 使用两个队列进行双向BFS:一个从初始状态开始,向目标状态移动。另一个从目标状态开始,向初始状态移动。
    • 对于两个队列中的每一个状态,它都会探索所有可能的移动,并更新访问状态和父节点信息。
    • 如果在两个访问数组中找到相同的状态,就可以利用print函数重构出解题路径。
  4. 路径重构(print):通过遍历pre[]数组来打印导致解决方案的一系列移动。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

筱姌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值