P8691 [蓝桥杯 2019 国 C] 填空问题 - 题解
冬令营结束了,做几道提答放松一下
没有题解,来写一篇(为什么通过率那么低?!)
题目传送门
试题 \mathrm{A} :奇数倍数
从小到大枚举
#include<iostream>
using namespace std;
bool judge(int x) {
while (x) {
if (x%2==0) return false;
else x/=10;
}
return true;
}
int main() {
int x=1;
while (!judge(2019*x)) x++;
cout<<2019*x<<endl;
return 0;
}
答案:
试题 \mathrm{B} : 递增序列
对于每一个字符,往右、下、右下、左下、右上看一看,数出分别能组成多少递增对,全部统计起来即可。代码如下:
#include<iostream>
using namespace std;
char c[35][55];
int cnt,n=30,m=50;
int main() {
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
cin>>c[i][j];
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++) {
for (int k=j+1;k<=m;k++)
if (c[i][j]<c[i][k])
cnt++;
for (int k=i+1;k<=n;k++)
if (c[i][j]<c[k][j])
cnt++;
for (int d=1; i+d<=n && j+d<=m; d++)
if (c[i][j]<c[i+d][j+d])
cnt++;
for (int d=1; i+d<=n && j-d>=1; d++)
if (c[i][j]<c[i+d][j-d])
cnt++;
for (int d=1; i-d>=1 && j+d<=m; d++)
if (c[i][j]<c[i-d][j+d])
cnt++;
}
cout<<cnt<<endl;
return 0;
}
答案:
试题 \mathrm{C} : 平方拆分
难度开始慢慢上去了。我一开始还看错题
考虑 DP。设
边界为
#include<iostream>
using namespace std;
int n=2019,f[2020][50];
int main() {
for (int i=0;i*i<=n;i++)
f[0][i]=1;
for (int i=1;i<=n;i++)
for (int j=0;j*j<=i;j++)
for (int k=j+1;k*k<=i;k++)
f[i][j]+=f[i-k*k][k];
cout<<f[n][0]<<endl;
return 0;
}
答案:
试题 \mathrm{D} : 最优旅行
一看到这题,我脑子里一声响。现实中的旅行商?!
图呢?别急,有个附件,下载下来。脑子里又一声响。
中文地名!?并且给的还不是边权,是起止时间?!
再仔细一看,(文件头两行表明)能有重边!?搞得我瞬间不想做了。。。
做完了“骰子制造”以后回来,静下心仔细想想,好像也没有那么恐怖。一共就
对于头两行,我们完全可以忽略第二行。因为如果我们第一站是从北京到上海,这两班车都可以乘坐(时间在十二点之后),而第一班车的到达时间比第二班早;如果不是,那么头两行就都不用考虑了。这样就解决了重边的问题。
题目中让我们求最小时间,限制了每个地点都要呆至少
妥妥的旅行商变种,用状压 DP 处理一下即可。注意在换高铁的时候可能要等到第二天,也可能在同一天,取决于上一辆车的到达时间与下一辆车的起始时间的大小关系。
代码如下:
#include<iostream>
#include<string>
using namespace std;
const int n=20, INF=0x3f3f3f3f;
string city[n]={"北京","上海","广州","长沙","西安","杭州","济南","成都","南京","昆明","郑州","天津","太原","武汉","重庆","南昌","长春","沈阳","贵阳","福州"};
int id(string s) {
for (int i=0;i<n;i++)
if (city[i]==s)
return i;
return -1;
}
int tim(string s) {
return ((s[0]-'0')*10+(s[1]-'0'))*60+((s[3]-'0')*10+(s[4]-'0'));
}
struct Train {
int st,en;
} g[n][n];
int dp[1<<n][n];
int dis(int now,int x,int y) { //重点!处理时间的函数
int t=now%1440; //上一班车的下车时间
int goal=now-t+g[x][y].en;
if (t>g[x][y].st) goal+=1440; //是否要多等一天,取决于上班车的下车时间和这班车的上车时间的大小关系
return goal;
}
int main() {
freopen("trip.txt","r",stdin);
for (int i=0;i<n;i++)
for (int j=0;j<n;j++)
g[i][j].st=g[i][j].en=-1;
string s;
cin>>s>>s>>s>>s>>s;
while (cin>>s) {
int x,y;
cin>>s; x=id(s);
cin>>s; y=id(s);
cin>>s; if (g[x][y].st==-1) g[x][y].st=tim(s);
cin>>s; if (g[x][y].en==-1) g[x][y].en=tim(s); //若有重边,之后读的丢弃,对应了头两行中保留第一行
}
for (int s=0;s<(1<<n);s++)
for (int i=0;i<n;i++)
dp[s][i]=INF;
dp[1][0]=720; //第一天中午
for (int s=0;s<(1<<n);s++)
for (int i=1;i<n;i++)
if (s&(1<<i))
for (int j=0;j<n;j++)
if ((s&(1<<j)) && g[j][i].st!=-1 && dp[s^(1<<i)][j]!=INF) {
int rec=dis(dp[s^(1<<i)][j],j,i); //利用 dis() 算出到达时间
if (rec<dp[s][i])
dp[s][i]=rec;
}
int ans=INF;
for (int i=1;i<n;i++)
if (g[i][0].st!=-1)
ans=min(ans,dis(dp[(1<<n)-1][i],i,0));
cout<<ans-720+1440*(n-1)<<endl; // 去掉多加的头半天,补上在每个城市各呆的一天
return 0;
}
结果:
试题 \mathrm{E} : 骰子制造
这是一道数学题,不需要写代码。
首先,两个骰子任意旋转之后不会相同,当且仅当:
-
两个骰子的面点的相对位置关系不同,或者
-
某一面的方向不同,导致点排列的形状不同。
两个骰子的面点的相对位置关系共有
在确定了骰子的面的位置关系后,我们知道,数
因此,总的骰子数为
答案:
最后提交的代码:
#include<iostream>
using namespace std;
int ans[5]={139311,52800,26287,41613,240};
int main() {
char c; cin>>c;
cout<<ans[c-'A']<<endl;
return 0;
}
结束了……吗?
然后我们惊讶地发现,第四个测试点错了!
我找出了测试点的正确输出:
(正文开始)
我花了大量的时间,调试测试点四,但就是找不出问题。
最终,我决定:让程序打印出路线,然后手算验证!
得到的结果为:
北京 天津 太原 郑州 西安 重庆 程度 昆明 南昌 福州
杭州 上海 南京 长沙 广州 贵阳 武汉 沈阳 长春 济南 北京
以下为涉及到的车次(全部出自附件):
G8901 北京 天津 22:10 22:45
G2609 天津 太原 10:40 14:15
G688 太原 郑州 17:38 21:38
G2001 郑州 西安 07:52 10:24
G2231 西安 重庆 17:06 22:56
G8594 重庆 成都 06:50 08:07
G2883 成都 昆明 08:51 14:29
G1514 昆明 南昌 16:00 22:54
G5314 南昌 福州 08:13 11:09
G1642 福州 杭州 14:45 18:32
G7558 杭州 上海 07:06 08:12
G7180 上海 南京 10:05 11:29
G579 南京 长沙 09:27 14:10
G6117 长沙 广州 17:55 20:39
G2960 广州 贵阳 07:27 13:43
G1524 贵阳 武汉 14:23 19:33
G1274 武汉 沈阳 07:23 19:03
G8033 沈阳 长春 06:42 08:40
G1242 长春 济南 15:33 22:35
G336 济南 北京 07:45 09:33
经过手算验证,小明于第一天十二点从北京出发,在第三十天九点三十三分回到北京,当中经过了
这个数值,已经小于答案
然后我又观察到,答案
于是我认为,有两种可能:
-
答案错了;
-
题意表述不明,或者漏了条件,导致理解上的错误
不管哪种情况,都希望题目能修正吧。这也是我写这篇题解的动机之一。经过观察,提交记录中很多人都是试错的,也有人做出
最后:本人第三篇题解,如有错误和建议欢迎指出(尤其是“最优旅行”)
我这篇题解或许大胆了一些,希望别出事。