2018北大计算机学科夏令营机试题目
题目链接
密码依然是fighting!
百练上北大夏令营的机试题目,全部拉到Virtual judge了 ,给我的感觉是2019的夏令营题目比2018难了一大截。不知道是偶然还是趋势。
A - 计算两个日期之间的天数
题目大意:计算两个日期差
题解:模拟水题,我用的是日期相减。没有写函数,导致中间一个变量用错了,Wa 2,绝了。以后还是多封装函数,不要写复制重复代码,就不贴代码了。
B - 回文子串
题目大意:
暴力找回文串
题解:
O(n^3)暴力即可
#include
#include
#include
#include
#include
#include
using namespace std;
string str;
bool is_ok(int i,int j){
while(str[i]==str[j]){
i++;
j--;
if(j<=i)return 1;
}
return 0;
}
int main()
{
cin>>str;
int n=str.length();
for(int i=2;i<=n;i++){
for(int j=0;j
C - The Die Is Cast
题目大意:
双层联通块
题解:
不知道网上题解怎么写的。我是找到第一层联通快,然后找第二层联通快。写了两个DFS,代码冗长。
#include
#include
#include
#include
#include
#include
#include
using namespace std;
char maze[55][55];
char temp[55][55];
char a[55][55];
bool vis[55][55];
bool vis2[55][55];
bool cur[55][55];
int dx[4]={1,-1,0,0};
int dy[4]={0,0,1,-1};
int w,h;
bool in(int x,int y){
if(x>=0&&x=0&&yve;
void gao(){
memset(vis2,0,sizeof vis2);
for(int i=0;i>w>>h&&w!=0){
cout<<"Throw "<<++T<>maze[i][j];
for(int i=0;i
D - 食物链
题目大意:
白书原题,很多人应该都写过
题解:
个人感觉采用一般并查集不是很好理解,下面采用带权并查集。带圈并查集才写了一个题,理解的肯定是不深刻。带权含义是每个节点到根节点的连线上存在一个权值,权值表示一定含义,节点合并时,需要加入权值信息,在路径压缩中,要保持每个节点到根节点权值不变,故需要做一些修改工作。本例中的三个种群分别代码节点到根节点的权值为0,1,2。
这个题神奇之处是,必须要scanf,cin会TLE。
#include
#include
#include
#include
#include
#include
using namespace std;
const int N=5e4+10;
int n,k;
int pre[N],val[N];
void init(){
for(int i=0;i<=n;i++)pre[i]=i,val[i]=0;
}
int find(int x){
int px=pre[x];
if(x!=pre[x]){
pre[x]=find(pre[x]);
val[x]=(val[x]+val[px])%3;
}
return pre[x];
}
int main()
{
scanf("%d%d",&n,&k);
int cnt=0;
init();
while(k--){
int d,x,y;
scanf("%d%d%d",&d,&x,&y);
int fx=find(x);
int fy=find(y);
if(x>n||y>n||(x==y&&d==2))cnt++;
else if(fx==fy&&(val[x]-val[y]+3)%3!=(d-1))cnt++;
else if(fx!=fy){
pre[fx]=fy;
val[fx]=(val[y]-val[x]+3+(d-1))%3;
}
}
cout<
E - 反正切函数的应用
题目大意:
二元(b,c)一次解方程,求满足条件的最小b+c的值。
题解:
有点像高中数学题,但是我没有想到解法。参考网上的,就是变量代换,代换两轮,变成对勾函数的形式,在转折点取到最小值,由于要求整数,所以要枚举。不知道什么只需要枚举左边就好了。
#include
#include
#include
#include
#include
#include
using namespace std;
int main()
{
long long a;
cin>>a;
for(int i=a;i>0;i--){
if((a*a+1)%i==0){
cout<<(i+(a*a+1)/i+2*a)<
F - Euro Efficiency
题目大意:
给定六种硬币面值[1,100),求拼出[1,100]的每个数,最少需要参与的硬币个数为多少。(各种硬币个数不限,可以找钱(也就是做减法))。
题解:
完全背包,背包问题必须要很熟悉,经常出现。我这里做法有点不一样,只做了一次完全背包,之后枚举给钱的总钱数,取一个min。
这个N值要稍大,给的钱数理论最大值为100*100。
输出用%.lf wa了,也是很神奇,网上说和%.f没有区别,以后还是%.f为妙。
#include
#include
using namespace std;
int price[6];
const int N=20000+10;
int dp[6][N];
int main()
{
int T;
cin>>T;
while(T--){
for(int i=0;i<6;i++){
cin>>price[i];
}
for(int i=0;i<6;i++){
for(int j=1;j=i;j--){
cur=min(cur,dp[5][j]+dp[5][j-i]);
}
maxx=max(cur,maxx);
all+=cur;
}
printf("%.2f %d\n",all/100.0,maxx);
}
return 0;
}
G - Tram
题目大意:
简单最短路
题解:
建图十分简单,边上的权值0或者1或者INF,再使用任意最短路算法,Floyd最简单,注意Floyd首先枚举中间点。
#include
#include
#include
#include
#include
#include
using namespace std;
const int N=105;
const int INF=0x3f3f3f;
int n,a,b;
int dis[N][N];
int main()
{
cin>>n>>a>>b;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
dis[i][j]=INF;
// if(i==j)dis[i][j]=0;
}
}
for(int i=1;i<=n;i++){
int k,e;
cin>>k;
for(int j=0;j>e;
if(j==0)dis[i][e]=0;
else dis[i][e]=1;
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int k=1;k<=n;k++){
dis[j][k]=min(dis[j][k],dis[j][i]+dis[i][k]);
}
if(dis[a][b]>=INF)cout<<-1<
H就不做了,逃。。。。。