考研算法
前言
本系列文章涉及的算法内容,针对的是哈尔滨工业大学854科目。在本文中通过具体的算法题进行讲解相应算法。
一、算法题目:
请输出 hello wangdao
解题思路:
考察C语言中printf函数的使用,注意OJ平台的换行(\n)
算法代码:
#include <stdio.h>
int main(){
printf("hello wangdao\n");
return 0;
}
二、算法题目:
计算a+b
解题思路:
熟悉C语言中的运算符,以及scanf函数的使用,注意输入输出的格式
算法代码:
#include <stdio.h>
int main(){
int a = 0, b = 0;
scanf("%d %d", &a, &b);
int res = a + b;
printf("%d\n", res);
return 0;
}
三、 算法题目:
读取一个65到122之间的整型数,然后以字符形式输出它
解题思路:
熟悉C语言中整形,实型,字符型变量的转换
算法代码:
#include <stdio.h>
int main(){
int n = 0;
scanf("%d", &n);
printf("%c", n);
return 0;
}
四、算法题目:
读取一个整型数,字符,浮点数,分别到变量i,j,k中,然后将i,j,k直接相加并输出,
小数点后保留两位小数,不用考虑输入的浮点数的小数部分超过了两位
解题思路:
熟悉C语言中的运算符,以及scanf函数的使用,
1、注意输入输出的格式记住字符输入时特点
2、以及输出格式的问题
算法代码:
#include<stdio.h>
int main(){
int i = 0;
char c = ' ';
float j = 0.0;
scanf("%d %c %f", &i, &c, &j);
float res = (float) i + (float)c + j;
printf("%.2f", res);
return 0;
}
五、算法题目:
输入一个整型数,判断是否是对称数,如果是,输出yes,否则输出no
解题思路:
了解对称数的概念,以及使用字符串的方式进行判断时下标和怎么比较字符串的每一个元素。
算法代码:
#include<stdio.h>
#include <stdbool.h>
int n = 0;
char str1[100];
char str2[100];
int i = 0;
bool flag = true;
void reverse(){
int tmp = n;
while(tmp != 0){
char c = tmp % 10;
str1[i++] = c;
tmp /= 10;
}
}
void isValid(){
int kk = 0;
for(int j = i - 1; j >= 0; --j){
str2[kk++] = str1[j];
}
for(int k = 0; k < i; ++k) {
if (((int) str1[k]) != ((int) str2[k])) {
flag = false;
break;
}
}
if(flag){
printf("yes\n");
}else{
printf("no\n");
}
}
int main(){
scanf("%d", &n);
reverse();
isValid();
return 0;
}
六、算法题目:
计算n!的值。
解题思路:
高精度阶乘模版,记住就好,如果想了解过程翻看前边的文章
算法代码:
#include<stdio.h>
#include <stdbool.h>
void highPrecisionFactorial(){
long ans[1000100];
long n;
scanf("%lld", &n);
ans[0] = 1;
int l = 0;
long num = 0;
for(int i = 1; i <= n; ++i)
{
num = 0;
for(int j = 0; j <= l; ++j){
num = num + ans[j] * i;
ans[j] = num % 10;
num /= 10;
}
while(num != 0){
ans[++l] = num % 10;
num /= 10;
}
}
for(int i = l ; i >= 0; --i){
printf("%d", ans[i]);
}
}
int main(){
highPrecisionFactorial();
return 0;
}
七、算法题目:
判断某个年份是不是闰年,如果是闰年,请输出“yes”,否则请输出“no”
解题思路:
记住:
1.普通年份能被4整除,且不能被100整除的,是闰年。(如2004年就是闰年)
2.世纪年份能被400整除的是闰年。(如2000年是闰年,1900年不是闰年)
3.对于数值很大的年份,这年如果能被3200整除,并且还能被172800整除的才是闰年。如172800年是闰年,86400年不是闰年(因为虽然能整除3200,但不能整除172800)。(此按一回归年365天5h48'45.5''计算)
算法代码:
#include<stdio.h>
int main(){
int n = 0;
scanf("%d", &n);
if((n % 4 == 0 && n % 100 != 0)
|| (n % 400 == 0)
|| (n % 3200 == 0 && n % 3200 == 0)){
printf("yes\n");
}
else{
printf("no\n");
}
return 0;
}
八、算法题目:
某人想将手中的一张面值100元的人民币换成10元、5元、2元和1元面值的票子。要求换正好40张,且每种票子至少一张。问:有几种换法?
解题思路:
暴力递归到动态规划,这个题比较简单,不做过多解释
算法代码:(暴力递归)
#include <stdio.h>
#include <stdbool.h>
int process(int arr[], int size, int i, int k, int rest){
if(k < 0 || rest < 0){
return 0;
}
if(i == size){
return k == 0 && rest == 0 ? 1 : 0;
}else{
long ans = 0;
for(int zhang = 0; zhang * arr[i] <= rest && zhang <= k; zhang++){
ans += process(arr, size, i + 1, k - zhang, rest - zhang * arr[i]);
}
return ans;
}
}
int ways0(int arr[], int aim, int size, int zhang){
int minus = 0;
for(int i = 0; i < size; ++i){
minus += arr[i];
}
aim -= minus;
zhang -= size;
if(aim < 0 || zhang < 0){
return 0;
}
return process(arr, size , 0, zhang, aim);
}
int main(){
int arr[] = {1, 2, 5, 10};
int n;
scanf("%d", &n);
int ans = ways0(arr, n, 4, 40);
printf("%d\n", ans);
return 0;
}
动态规划:
int ways2(int arr[], int size, int aim, int zhang){
int minus = 0;
for(int i = 0; i < size; ++i){
minus += arr[i];
}
aim -= minus;
zhang -= size;
if(aim < 0 || zhang < 0){
return 0;
}
int dp[size + 1][zhang + 1][aim + 1];
memset(dp, 0, sizeof(int) * (size + 1) * (zhang + 1) * (aim + 1));
dp[size][0][0] = 1;
for(int i = size - 1; i >= 0; --i){
for(int k = 0; k <= zhang; ++k){
for(int rest = 0; rest <= aim; ++rest){
dp[i][k][rest] = dp[i + 1][k][rest];
if(k - 1 >= 0 && rest - arr[i] >= 0){
dp[i][k][rest] += dp[i][k - 1][rest - arr[i]];
}
}
}
}
return dp[0][zhang][aim];
}
int main(){
int arr[] = {1, 2, 5, 10};
int n;
scanf("%d", &n);
int ans = ways2(arr, 4, n, 40);
printf("%d\n", ans);
return 0;
}