HDU1510——White Rectangles(白色矩形)
题目描述
运行代码
#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;
}
代码思路
-
函数
countWhiteRectangles
:- 初始化高度数组:首先,通过两层循环遍历输入的棋盘,对于每个格子,如果是白色方块(
.
),则将其上方连续白色格子的数量设置为上一行对应位置的数量加一,如果是黑色方块(#
)则设置为零。这样就得到了一个表示每个格子向上连续白色格子数量的二维数组high
。 - 计算白色矩形数量:然后,通过两层嵌套循环遍历棋盘的每个位置。对于每个位置
(i, j)
,先将当前位置的高度high[i][j]
作为最小高度minHigh
,并将其加入总数total
。接着,向左遍历当前行的前面的位置,对于每个位置(i, k)
,如果该位置的高度小于当前最小高度,则更新最小高度为high[i][k]
,并将最小高度加入总数total
。这样就计算出了以当前位置为右下角的所有白色矩形的数量。 - 返回总数:最后,函数返回总数
total
,即棋盘上所有白色矩形的数量。
- 初始化高度数组:首先,通过两层循环遍历输入的棋盘,对于每个格子,如果是白色方块(
-
主函数
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;
}
代码思路
-
函数
factorial
:这个函数用于计算给定整数的阶乘。通过一个循环从2
到n
累乘,得到n
的阶乘值。 -
函数
permutation
:接收两个整数m
和n
,用于计算排列数A(m, n)
。根据排列数的计算公式A(m, n) = m! / (m - n)!
,调用factorial
函数分别计算m
的阶乘和m - n
的阶乘,然后相除得到排列数。 -
函数
combination
:接收两个整数m
和n
,用于计算组合数C(m, n)
。根据组合数的计算公式C(m, n) = m! / (n! * (m - n)!)
,调用factorial
函数分别计算m
、n
和m - n
的阶乘,然后进行相应的计算得到组合数。 -
主函数
main
:首先读取测试用例的数量T
。然后进入一个循环,循环次数为T
。在每次循环中,读取操作符op
、整数m
和n
。根据操作符判断是计算排列数还是组合数,调用相应的函数进行计算,并输出结果。
HDU1716——排列2
题目描述
运行代码
#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,则程序结束。
二、具体函数分析
-
函数
FN
:- 排序输入数字:首先使用
std::sort
对输入的数字向量cards
进行排序,确保初始状态是最小的排列。这样在后续使用std::next_permutation
生成排列时,可以保证顺序是从小到大的。 - 生成并输出四位数:使用
do-while
循环结合std::next_permutation
来生成所有可能的排列。在每次循环中,如果千位数字(即cards[0]
)为 0,则跳过当前排列,因为四位数的千位不能为 0。使用stringstream
将当前排列的四个数字拼接成一个四位数的字符串表示。为了实现千位数字相同的放在同一行输出的功能,引入了一个静态变量prevThousands
来记录上一个输出的四位数的千位数字。如果当前四位数的千位数字与上一个不同,就输出一个换行符,然后更新prevThousands
。接着输出当前四位数。 - 输出换行符:在循环结束后,输出一个换行符,以便在不同的输入之间进行区分。
- 排序输入数字:首先使用
-
主函数
main
:- 输入处理循环:创建一个长度为 4 的整数向量
cards
来存储四张卡片的数字。使用一个无限循环来读取输入的卡片数字。对于每次输入,循环遍历cards
的每个元素,从标准输入读取一个数字赋值给对应的元素。 - 结束条件判断:如果输入的四个数字都是 0,则跳出循环,结束程序。
- 调用函数并输出换行符:对于每组输入的卡片数字,调用
FN
函数来生成并输出所有可能的四位数排列。在每组输出之后,再输出一个换行符,以便在不同的输入之间进行区分。
- 输入处理循环:创建一个长度为 4 的整数向量
next_permutation的用法
std::next_permutation
是一个算法函数,用于生成给定序列的下一个字典序排列。
template <class BidirectionalIterator>
bool next_permutation (BidirectionalIterator first, BidirectionalIterator last);
first
和last
定义了一个范围,这个范围通常是一个容器(如std::vector
、std::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 3
、1 3 2
、2 1 3
、2 3 1
、3 1 2
、3 2 1
,即整数数组 {1, 2, 3}
的所有可能的排列。
注意,要使用 std::next_permutation
,容器中的元素必须是可比较的,并且容器中的元素必须支持通过迭代器进行的随机访问。