HDU1510——White Rectangles(白色矩形),HDU1570——A C,HDU1716——排列2,next_permutation的用法

38 篇文章 0 订阅

HDU1510——White Rectangles(白色矩形)

题目描述

Problem - 1510 (hdu.edu.cn)

运行代码

#include <iostream>
#include <vector>

using namespace std;

int countWhiteRectangles(vector<vector<char>>& board) {
    int n = board.size();
    vector<vector<int>> high(n, vector<int>(n, 0));
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            if (board[i][j] == '.')
                high[i][j] = (i > 0 ? high[i - 1][j] : 0) + 1;
            else
                high[i][j] = 0;
        }
    }
    int total = 0;
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            int minHigh = high[i][j];
            total += minHigh;
            for (int k = j - 1; k >= 0; --k) {
                if (high[i][k] < minHigh)
                    minHigh = high[i][k];
                total += minHigh;
            }
        }
    }
    return total;
}

int main() {
    int n;
    while (cin >> n) {
        vector<vector<char>> board(n, vector<char>(n));
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                cin >> board[i][j];
            }
        }
        cout << countWhiteRectangles(board) << endl;
    }
    return 0;
}

代码思路

  1. 函数 countWhiteRectangles

    • 初始化高度数组:首先,通过两层循环遍历输入的棋盘,对于每个格子,如果是白色方块(.),则将其上方连续白色格子的数量设置为上一行对应位置的数量加一,如果是黑色方块(#)则设置为零。这样就得到了一个表示每个格子向上连续白色格子数量的二维数组 high
    • 计算白色矩形数量:然后,通过两层嵌套循环遍历棋盘的每个位置。对于每个位置 (i, j),先将当前位置的高度 high[i][j] 作为最小高度 minHigh,并将其加入总数 total。接着,向左遍历当前行的前面的位置,对于每个位置 (i, k),如果该位置的高度小于当前最小高度,则更新最小高度为 high[i][k],并将最小高度加入总数 total。这样就计算出了以当前位置为右下角的所有白色矩形的数量。
    • 返回总数:最后,函数返回总数 total,即棋盘上所有白色矩形的数量。
  2. 主函数 main

    • 首先,读取输入的棋盘大小 n
    • 然后,创建一个大小为 n 的二维字符向量 board 来存储棋盘的状态。
    • 接着,通过两层循环读取输入的棋盘状态,每行的字符依次存入 board
    • 最后,调用 countWhiteRectangles 函数计算并输出白色矩形的数量。

HDU1570——A C

题目描述

运行代码

#include <iostream>

using namespace std;

// 计算阶乘
long long factorial(int n) {
    long long result = 1;
    for (int i = 2; i <= n; ++i) {
        result *= i;
    }
    return result;
}

// 计算排列数 A(m, n)
long long permutation(int m, int n) {
    return factorial(m) / factorial(m - n);
}

// 计算组合数 C(m, n)
long long combination(int m, int n) {
    return factorial(m) / (factorial(n) * factorial(m - n));
}

int main() {
    int T;
    cin >> T;
    while (T--) {
        char op;
        int m, n;
        cin >> op >> m >> n;
        if (op == 'A') {
            cout << permutation(m, n) << endl;
        } else if (op == 'C') {
            cout << combination(m, n) << endl;
        }
    }
    return 0;
}

代码思路

  1. 函数 factorial:这个函数用于计算给定整数的阶乘。通过一个循环从 2 到 n 累乘,得到 n 的阶乘值。

  2. 函数 permutation:接收两个整数 m 和 n,用于计算排列数 A(m, n)。根据排列数的计算公式 A(m, n) = m! / (m - n)!,调用 factorial 函数分别计算 m 的阶乘和 m - n 的阶乘,然后相除得到排列数。

  3. 函数 combination:接收两个整数 m 和 n,用于计算组合数 C(m, n)。根据组合数的计算公式 C(m, n) = m! / (n! * (m - n)!),调用 factorial 函数分别计算 mn 和 m - n 的阶乘,然后进行相应的计算得到组合数。

  4. 主函数 main:首先读取测试用例的数量 T。然后进入一个循环,循环次数为 T。在每次循环中,读取操作符 op、整数 m 和 n。根据操作符判断是计算排列数还是组合数,调用相应的函数进行计算,并输出结果。

HDU1716——排列2

题目描述

Problem - 1716 (hdu.edu.cn)

运行代码

#include <iostream>
#include <vector>
#include <algorithm>
#include <sstream>

using namespace std;

void FN(vector<int>& cards) {
    sort(cards.begin(), cards.end());
    do {
        if (cards[0] == 0) continue;
        stringstream ss;
        for (int card : cards) {
            ss << card;
        }
        int thousands = cards[0];
        static int prevThousands = -1;
        if (thousands != prevThousands) {
            if (prevThousands != -1) cout << endl;
            prevThousands = thousands;
        }
        cout << ss.str() << " ";
    } while (next_permutation(cards.begin(), cards.end()));
    cout << endl;
}

int main() {
    vector<int> cards(4);
    while (true) {
        for (int& card : cards) {
            cin >> card;
        }
        if (cards[0] == 0 && cards[1] == 0 && cards[2] == 0 && cards[3] == 0) break;
        FN(cards);
        cout << endl;
    }
    return 0;
}

代码思路

一、整体思路

这段代码的目的是对于输入的四个数字(代表四张卡片上的数字),生成由这四个数字组成的所有可能的四位数,并按照特定规则进行输出。具体规则为:将千位数字相同的四位数放在同一行输出,并且输出结果按照从小到大的顺序排列。如果输入的四个数字都是 0,则程序结束。

二、具体函数分析

  1. 函数 FN

    • 排序输入数字:首先使用 std::sort 对输入的数字向量 cards 进行排序,确保初始状态是最小的排列。这样在后续使用 std::next_permutation 生成排列时,可以保证顺序是从小到大的。
    • 生成并输出四位数:使用 do-while 循环结合 std::next_permutation 来生成所有可能的排列。在每次循环中,如果千位数字(即 cards[0])为 0,则跳过当前排列,因为四位数的千位不能为 0。使用 stringstream 将当前排列的四个数字拼接成一个四位数的字符串表示。为了实现千位数字相同的放在同一行输出的功能,引入了一个静态变量 prevThousands 来记录上一个输出的四位数的千位数字。如果当前四位数的千位数字与上一个不同,就输出一个换行符,然后更新 prevThousands。接着输出当前四位数。
    • 输出换行符:在循环结束后,输出一个换行符,以便在不同的输入之间进行区分。
  2. 主函数 main

    • 输入处理循环:创建一个长度为 4 的整数向量 cards 来存储四张卡片的数字。使用一个无限循环来读取输入的卡片数字。对于每次输入,循环遍历 cards 的每个元素,从标准输入读取一个数字赋值给对应的元素。
    • 结束条件判断:如果输入的四个数字都是 0,则跳出循环,结束程序。
    • 调用函数并输出换行符:对于每组输入的卡片数字,调用 FN 函数来生成并输出所有可能的四位数排列。在每组输出之后,再输出一个换行符,以便在不同的输入之间进行区分。

next_permutation的用法

std::next_permutation 是一个算法函数,用于生成给定序列的下一个字典序排列。

template <class BidirectionalIterator>
bool next_permutation (BidirectionalIterator first, BidirectionalIterator last);
  • first 和 last 定义了一个范围,这个范围通常是一个容器(如 std::vectorstd::array 或 std::string)的迭代器区间,表示要进行排列操作的序列。
  • 如果成功地生成了下一个字典序排列,则返回 true;如果当前序列已经是最后一个可能的排列(即字典序最大的排列),则将序列重新排列为字典序最小的排列,并返回 false
#include <iostream>
#include <algorithm>
#include <vector>

int main() {
    std::vector<int> v = {1, 2, 3};

    do {
        for (int num : v) {
            std::cout << num << " ";
        }
        std::cout << std::endl;
    } while (std::next_permutation(v.begin(), v.end()));

    return 0;
}

程序会输出 1 2 31 3 22 1 32 3 13 1 23 2 1,即整数数组 {1, 2, 3} 的所有可能的排列。

注意,要使用 std::next_permutation,容器中的元素必须是可比较的,并且容器中的元素必须支持通过迭代器进行的随机访问。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

筱姌

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

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

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

打赏作者

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

抵扣说明:

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

余额充值