2076.夹角有多大(题目已修改,注意读题)
题目描述
http://acm.hdu.edu.cn/showproblem.php?pid=2076
Problem Description
时间过的好快,一个学期就这么的过去了,xhd在傻傻的看着表,出于对数据的渴望,突然他想知道这个表的时针和分针的夹角是多少。现在xhd知道的只有时间,请你帮他算出这个夹角。
注:夹角的范围[0,180],时针和分针的转动是连续而不是离散的。
Input
输入数据的第一行是一个数据T,表示有T组数据。
每组数据有三个整数h(0 <= h < 24),m(0 <= m < 60),s(0 <= s < 60)分别表示时、分、秒。
Output
对于每组输入数据,输出夹角的大小的整数部分。
运行代码
#include <iostream>
#include <cmath>
using namespace std;
int main() {int T;cin >> T;for (int i = 0; i < T; i++) {double h, m, s;cin >> h >> m >> s;h = h > 12 ? h - 12 : h;double H = h * 30.0 + m * 0.5 + 1.0 / 120.0 * s;double M = m * 6.0 + s * 0.1;double a = abs(H - M);a = a > 180 ? 360 - a : a;cout << (int)a << endl;}return 0;
}
代码思路
-
输入处理:首先,接收一个整数
T
,表示需要处理的测试用例数量。然后,对于每个测试用例,读入三个浮点数h
,m
,s
,分别代表小时、分钟和秒。 -
计算时针与分针的角度位置:
- 由于一天有24小时,但时钟上两针的最大夹角不会超过180度(考虑一圈为360度,从一个数字到下一个数字为30度),因此如果输入的小时数大于12,说明是下午或晚上的时间,需要减去12来适应时钟计算(但这一步骤实际上对计算两针夹角不是必需的,因为后面计算时会以0-12小时制为基础进行转换)。
- 计算时针的位置:每小时时针走30度,每分钟时针额外走0.5度(因为一小时60分钟,共走30度,所以每分钟0.5度),再加上每秒钟时针微小的移动,即1/120度(因为一分钟时针走0.5度,60秒走完这0.5度,所以一秒走1/120度)。
- 计算分针的位置:每分钟分针走6度,加上每秒走0.1度(因为一分钟走6度,60秒走完这6度)。
-
计算两针夹角:计算两针相对于12点位置的角度差
a
,取绝对值,即abs(H - M)
。如果这个差值大于180度,说明我们计算的是“外侧”夹角,实际“内侧”夹角应该是360度减去这个差值,即360 - a
。 -
输出结果:将计算得到的两针之间的最小角度转换为整数并输出。
综上,该程序实现了根据给定的时间计算时针与分针之间的最小角度差的功能。注意,代码中直接对小时数进行h > 12 ? h - 12 : h
的处理其实对于最终计算角度是多余的,因为计算角度时直接根据0-12小时制就能正确反映实际情况。
2077.汉诺塔IV
题目描述
http://acm.hdu.edu.cn/showproblem.php?pid=2077
Problem Description
还记得汉诺塔III吗?他的规则是这样的:不允许直接从最左(右)边移到最右(左)边(每次移动一定是移到中间杆或从中间移出),也不允许大盘放到小盘的上面。xhd在想如果我们允许最大的盘子放到最上面会怎么样呢?(只允许最大的放在最上面)当然最后需要的结果是盘子从小到大排在最右边。
Input
输入数据的第一行是一个数据T,表示有T组数据。
每组数据有一个正整数n(1 <= n <= 20),表示有n个盘子。
Output
对于每组输入数据,最少需要的摆放次数。
运行代码
#include <iostream>
using namespace std;
long long FN(int n, int e) {long long m = 1;for (int i = 1; i <= e; ++i) {m *= n;}return m;
}
int main() {int n;cin >> n;while (n--) {int N;while (cin >> N) {cout << FN(3, N - 1) + 1 << endl;}}return 0;
}
代码思路
-
定义计算函数
FN(int n, int e)
:这个函数接收两个整数参数:n
和e
。函数内部通过一个循环计算n
的e
次方(即n
乘以自身e
次)。这是通过初始化一个长整型变量m
为 1,然后在循环中不断将m
乘以n
来实现的。循环结束后,返回计算得到的n
的e
次方值。 -
主函数
main()
:首先,读取一个整数n
,表示接下来将有多少组输入数据。然后,进入一个while
循环,该循环会运行n
次,处理每组输入数据。在这内部,使用另一个while
循环持续读取整数N
,直到遇到文件结束或者输入错误等停止条件(注意,这里没有明确的停止条件来终止内部循环,理论上会一直等待输入直到程序外部干预)。对于每读取到的一个N
值:最后输出这个计算结果。然后将计算结果加 1。调用之前定义的FN
函数计算3
的 (N
- 1) 次方。主函数结束后,程序返回 0,表示正常退出。
功能解释: 本质上,对于每组输入的 N
,程序计算并输出的是 3^(N-1) + 1
的值。
2078.复习时间
题目描述
http://acm.hdu.edu.cn/showproblem.php?pid=2078
Problem Description
为了能过个好年,xhd开始复习了,于是每天晚上背着书往教室跑。xhd复习有个习惯,在复习完一门课后,他总是挑一门更简单的课进行复习,而他复习这门课的效率为两门课的难度差的平方,而复习第一门课的效率为100和这门课的难度差的平方。xhd这学期选了n门课,但是一晚上他最多只能复习m门课,请问他一晚上复习的最高效率值是多少?
Input
输入数据的第一行是一个数据T,表示有T组数据。
每组数据的第一行是两个整数n(1 <= n <= 40),m(1 <= m <= n)。
接着有n行,每行有一个正整数a(1 <= a <= 100),表示这门课的难度值。
Output
对于每组输入数据,输出一个整数,表示最高效率值。
运行代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {int t;cin >> t;while (t--) {int n, m;cin >> n >> m;vector<int> s(n);for (int i = 0; i < n; i++) {cin >> s[i];}sort(s.begin(), s.end());cout << (100 - s[0]) * (100 - s[0]) << endl;}return 0;
}
代码思路
-
输入处理:首先,读取一个整数
t
,表示有t
组测试用例。使用while (t--)
循环来处理每一组测试用例。 -
每组测试用例处理:对于每组测试用例,先读取两个整数
n
和m
,其中n
表示接下来要输入的整数个数,而m
在这个程序中没有实际用途。定义一个大小为n
的vectors
来存储这n
个整数。使用一个循环读取这n
个整数,并将它们存入vectors
中。 -
数据处理:使用
sort(s.begin(), s.end())
对vectors
中的元素进行升序排序。计算排序后序列中第一个元素(即最小元素)与100的差的平方,公式为(100 - s[0]) * (100 - s[0])
。输出这个计算结果。 -
循环结束与程序终止:当所有测试用例处理完毕后,程序结束并返回0,表示正常退出。
2079.选课时间
题目描述
http://acm.hdu.edu.cn/showproblem.php?pid=2079
Problem Description
又到了选课的时间了,xhd看着选课表发呆,为了想让下一学期好过点,他想知道学n个学分共有多少组合。你来帮帮他吧。(xhd认为一样学分的课没区别)
Input
输入数据的第一行是一个数据T,表示有T组数据。
每组数据的第一行是两个整数n(1 <= n <= 40),k(1 <= k <= 8)。
接着有k行,每行有两个整数a(1 <= a <= 8),b(1 <= b <= 10),表示学分为a的课有b门。
Output
对于每组输入数据,输出一个整数,表示学n个学分的组合数。
运行代码
#include <iostream>
#include <vector>
using namespace std;
int dp[41][41];
int main() {int T;cin >> T;while (T--) {int n, k;cin >> n >> k;vector<pair<int, int>> c(k);for (int i = 0; i < k; i++) {int a, b;cin >> a >> b;c[i] = { a, b };}for (int i = 0; i <= n; i++) {for (int j = 0; j <= k; j++) {dp[i][j] = 0;}}dp[0][0] = 1;for (int i = 0; i < k; i++) {for (int j = 0; j <= n; j++) {for (int l = 0; l <= c[i].second && j + l * c[i].first <= n; l++) {dp[j + l * c[i].first][i + 1] += dp[j][i];}}}cout << dp[n][k] << endl;}return 0;
}
代码思路
-
输入处理:首先,读入测试用例的总数
T
。对于每个测试用例,读入总学分n
和物品(课程)种类数k
。然后,读入每种物品(硬币)的价值和对应的数量 -
初始化DP表:
- 初始化一个二维数组
dp
,其中dp[i][j]
表示在前j
种物品中选取总价值恰好为i
的组合数。数组的大小为(n+1) x (k+1)
,其中dp[0][0]
初始化为1,表示没有任何物品时,总价值为0有一种方式(即不选任何物品)。
- 初始化一个二维数组
-
动态规划转移:通过三层循环进行动态规划状态转移:外层循环遍历所有物品(课程)种类
i
(从0到k-1
)。中层循环遍历所有可能的总金额j
(从0到n
)。内层循环遍历当前物品(课程)可以使用的数量l
(从0到其最大使用数量,即保证总金额不超过n
且不超过该课程总学分的限制),并更新dp[j + l*c[i].first][i + 1]
,即将当前物品使用l
个时,能够达到的新总金额的组合数累加到对应的状态上。 -
输出结果:对于每个测试用例,最终答案是
dp[n][k]
,即所有物品都考虑过时,总学分为n
的组合数。