题目1:结果填空:18岁生日
代码如下:
#include<bits/stdc++.h>
using namespace std;
bool leap(int year)
{
if(year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) return true;
return false;
}
int main()
{
int sum = 0;
for(int i = 0;i < 18;i++){
if(leap(i + 2015)) sum += 366;
else sum += 365;
}
cout << sum << endl;
return 0;
}
最终答案:6575
这道题非常简单,只要判断从2015年一直到2032年期间每一年是平年还是闰年就可以了,平年天数加365,闰年天数加366。
题目2:结果填空:数字拆分
代码如下:
#include<bits/stdc++.h>
using namespace std;
int dp[100];
int main()
{
int n;
cin >> n;
dp[0] = 1;
for(int i = 1;i <= n;i++){
for(int j = i;j <= n;j++){
dp[j] += dp[j - i];
}
}
cout << dp[n] << endl;
return 0;
}
最终答案:42
这道题和背包问题种的完全背包问题很类似,假设要分解的数为n,那么就相当于从1,2,3…n这些数中任取,取出来所有的数之和为n就可以了,这里的1,2…n这些数取的次数是没有限制的。上述代码写的是经过空间压缩得出的。
题目3:结果填空:一笔画
代码如下:
#include<bits/stdc++.h>
using namespace std;
int ans = 0,dir[4][2] = {{1,0},{0,1},{-1,0},{0,-1}};
bool vis[3][5];
void dfs(int x,int y,int step)
{
cout << x << " " << y << " " << step << endl;
if(x == 2 && y == 0){
if(step == 15) ans++;
return;
}
for(int i = 0;i < 4;i++){
int tx = x + dir[i][0];
int ty = y + dir[i][1];
if((!vis[tx][ty]) && tx >= 0 && tx < 3 && ty >= 0 && ty < 5){
vis[x][y] = true;
dfs(tx,ty,step + 1);
vis[x][y] = false;
}
}
}
int main()
{
vis[0][0] = true;
dfs(0,0,1);
cout << ans << endl;
return 0;
}
最终答案为:4
这道题我是用dfs去完成的,将初始的位置和步数传入函数,刚开始从1步算起。每次走到位置(2,0),且步数达到15,可能数就累加一次,因为代表这是一种能达到终点的可能,且路过所有格子。最终次数就是能走到出口且路过所有格子的方案数。
题目4:结果填空:排列
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int MAX = 1e9 + 7;
long long dp[20][1 << 20];//表示第i行状态为j的所有可能
int state[1 << 20],sum = 0;
int main()
{
long long n,k = 0;
cin >> n;
dp[0][0] = 1;
for(int i = 0;i < (1 << n);i++){
if(!(i & (i >> 1))) state[k++] = i;//选出所有的可能保存下来,确保每次选的右边都没人
}
for(int i = 1;i <= n;i++){
for(int j = 0;j < k;j++){
for(int a = 0; a < k;a++){
if(!(state[j] & state[a])){ //保存下边没人坐
dp[i][j] += dp[i - 1][a];//第i行状态为j的所有可能等于第i - 1行所有的状态数之和
dp[i][j] %= MAX;
}
}
if(i == n) sum += dp[i][j],sum %= MAX;
}
}
cout << sum << endl;
return 0;
}
这道题是一道典型的状压dp,看了好久题解才明白。首先保存出所有一排位置坐人的可能状态,i & (i >> 1)作用是排除左右坐人的可能,然后一排一排开始累计所有的可能,到最后一排的时候把所有的可能加起来就是总和。
不懂状压dp的人可以看https://blog.csdn.net/u011077606/article/details/43487421,个人感觉写的很好。
题目5:代码填空:排序
代码如下:
#include <bits/stdc++.h>
using namespace std;
const int N = 110;
int a[N];
int main() {
int n;
cin >> n;
for (int i = 0; i < n; i++) {
int x;
cin >> x;
a[x]++;
}
for (int i = 100; i >= 0; i--) {
for(int j = a[i];j > 0;j--) {
cout << i << endl;
}
}
return 0;
}
答案:for(int j = a[i];j > 0;j--)
这就是一道桶排序问题,非常简单,注意检验答案的时候可以输入几个重复的成绩来验证一下。