这几个系列里有重复的题我都没有做,每个题就出现一次,大家看完整个系列就OK。
补一句,2015年的题真的很顶。
西工大计算机复试2017篇
1.输入两组时间(h,m,s),计算平均时间。两组时间不超过一个小时,h在0-11之间
Input:
1 20 30 1 30 30
0 20 30 11 30 30
Output:
1 25 30
11 55 30
解析:注意这里有个坑,两组时间不超过一个小时,且j介于0-11之间,所以例二应该是11:30:30在前,0:20:30在后。此题不难,但需要思考出良好的解法才行,暴力解可行,但有点麻烦。
代码:
#include<iostream>
using namespace std;
int CalSec(int h1,int m1,int s1,int h2,int m2,int s2)
{
return ((h1+h2)*3600+(m1+m2)*60+s2+s1)/2;
}
int main()
{
int h1,m1,s1,h2,m2,s2;
while(cin>>h1>>m1>>s1>>h2>>m2>>s2)
{
int sec=0;
int m,s,h;
if(h1==11&&h2==0)
{
sec+=CalSec(h1,m1,s1,12,m2,s2);
h=sec/3600;
m=(sec%3600)/60;
s=(sec%3600)%60;
}
else if(h2==11&&h1==0)
{
sec+=CalSec(12,m1,s1,11,m2,s2);
h=sec/3600;
m=(sec%3600)/60;
s=(sec%3600)%60;
}
else
{
sec+=CalSec(h1,m1,s1,h2,m2,s2);
h=sec/3600;
m=(sec%3600)/60;
s=(sec%3600)%60;
}
if(h==12)
h=0;
cout<<h<<" ";
cout<<m<<" ";
cout<<s<<endl;
}
return 0;
}
2.输入行数,再在每行输入一个表达式,得出结果
Input:
3
1+1
2.2/3
1+2*3+2
Output:
2
0.7
9
解析:此处这个题没有涉及到括号,所以不难,可以不用数据结构解开。我会补一篇包含括号的,用要到栈和队列。
代码:
#include<iostream>
#include<stdio.h>
using namespace std;
int main()
{
int n;
cin>>n;
while(n--)
{
double a[20];
double sum=0;
cin>>a[0];
char c;
c=getchar();
int i=0;
while(c!='\n')
{
double tmp;
cin>>tmp;
switch(c)
{
case '+':a[++i]=tmp;break;
case '-':a[++i]=-tmp;break;
case '*':a[i]*=tmp;break;
case '/':a[i]/=tmp;break;
}
c=getchar();
}
for(int j=0;j<=i;j++)
sum=sum+a[j];
if(sum-int(sum)<=1e-6)
printf("%.0f\n",sum);
else
printf("%.1lf\n",sum);
}
return 0;
}
西工大计算机复试2016篇
1.小王围操场跑圈,每次跑三圈,请输入行数,每行输入九个整数,表示每圈所用的分,秒和毫秒。输出每次跑步所用的平均时间。
输入示例:
2
1 10 100 1 20 100 1 30 100
2 10 100 1 20 100 1 30 100
输出示例:
1 20 100
1 40 100
解析:沿用一贯做法,加和再做平均数。
代码:
#include<iostream>
#include<stdio.h>
using namespace std;
struct TNode{
int m;
int s;
int ms;
};
int main()
{
int n;
cin>>n;
while(n--)
{
struct TNode t1,t2,t3;
cin>>t1.m>>t1.s>>t1.ms;
cin>>t2.m>>t2.s>>t2.ms;
cin>>t3.m>>t3.s>>t3.ms;
int em,es,ems;
int sum=0;
sum+=(t1.m+t2.m+t3.m)*60*1000+(t1.s+t2.s+t3.s)*1000+t1.ms+t2.ms+t3.ms;
sum=sum/3;
em=sum/60000;
es=(sum%60000)/1000;
ems=(sum%60000)%1000;
cout<<em<<" ";
cout<<es<<" ";
cout<<ems<<endl;
}
return 0;
}
西工大计算机复试2015篇
1.求最小数,给定三个数(int型),输出最小的数
Input:
5 2 55
output:
2
2.十进制转换为二进制
input:
1030
otput:
10000000110
解析:上两题过于简单,不做。
3.计算单词个数:给一行句子,写一个程序判断它有几个单词。
输入占一行,只包含大小写字母和空格,输出单词的个数。
输入样例:
genaral game players are systems to
输出样例:
7
解析:注意想清楚各种情况,如最后一个字符是单词或者空格或者连几个空格。
代码:
#include<iostream>
#include<stdio.h>
using namespace std;
int main()
{
int num=0;
string str;
int i;
getline(cin,str);
int len=str.size();
for(i=0;i<len;i++)
{
if(str[i]!=' ')
break;
}
for(;i<len-1;i++)
{
if(str[i]==' '&&str[i+1]!=' ')
num++;
}
if(str[len-1]!=' ')
num++;
if(str[len-1]==' '&&str[len-2]!=' ')
num++;
cout<<num<<endl;
return 0;
}
4.字符串替换问题:输入三个字符串a,b和c,将a中第一次出现b的地方替换为c
输入样例
abcdefg
cde
xiaolan
输出样例
abxiaolanfg
解析:此题可以用字符数组解决,但比较麻烦,此处介绍replace函数,可直接使用。(C++永远的神)
代码:
#include<iostream>
#include<string>
using namespace std;
int main()
{
string s[3];
for(int i=0;i<3;i++)
getline(cin,s[i]);
int pos=s[0].find(s[1]);
s[0]=s[0].replace(pos,s[1].size(),s[2]);
cout<<s[0]<<endl;
return 0;
}
5.迷宫问题
6.迷宫问题2
解析:这两个题看着很吓人,,,,其实很简单,判断一下要走位置是不是墙即可,所以不做。下面附一个走迷宫问题,使用广搜,比较有参考价值。
8.连阴雨问题:因为下雨,地上有很多水,W代表积水,.代表干燥,我们将“相邻”定位为八个方向,相邻的积水构成一个水坑,先输入M,N,再输入一个M行N列字符矩阵,输出互不相邻的水坑个数。
输入样例:
10 12
W........WW.
.WWW.....WWW
....WW...WW.
.........WW.
.........W..
..W......W..
.W.W.....WW.
W.W.W.....W.
.W.W......W.
..W.......W.
输出样例:
3
解析:说一下思路。挨个判断,对于每个,判断其周围的八个位置有没有水,若有进一步判断这个水是不是被用过,若没用过,水坑数加一,used数组置为1即可,并且周围的水也都置为1。
代码:
#include<iostream>
#include<string>
#include<stdio.h>
using namespace std;
int main()
{
int dirx[8]={-1,0,1,1,1,0,-1,-1};
int diry[8]={1,1,1,0,-1,-1,-1,0};
int m,n;
int a[20][20],used[20][20]={0};
cin>>m>>n;
int num=0;
getchar();
char c;
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
c=getchar();
if(c=='W')
a[i][j]=0;//积水
else
a[i][j]=1;//干燥
}
getchar();
}
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
if(a[i][j]==0)//对于每个水坑
{
int flag=0;
for(int k=0;k<8;k++)
{//判断八个方位是否有水
int x=i+dirx[k];
int y=j+diry[k];
if(x>=0&&x<=m&&y>=0&&y<=n)//方位是否合法
{
if(used[x][y]==1&&a[x][y]==0)//一旦有一个用过的水坑
{
flag=1;
break;
}
}
}
//被用过,则周围的水坑都used置为1,num不加
//若没用过,同样置为1,但num++
if(flag==0)
num++;
used[i][j]=1;
for(int k=0;k<8;k++)
{
int x=i+dirx[k];
int y=j+diry[k];
if(x>=0&&x<=m&&y>=0&&y<=n)
if(used[x][y]==0&&a[x][y]==0)
used[x][y]=1;
}
}
}
}
cout<<num<<endl;
return 0;
}
7.六数码问题:
现有一两行三列的表格如下:
A B C
D E F
把1、2、3、4、5、6六个数字分别填入A、B、C、D、E、F格子中,每个格子一个数字且各不相同。每种不同的填法称为一种布局。如下:
布局1:1 3 5
2 4 6
布局2:2 5 6
4 3 1
定义α变换如下:把A格中的数字放入B格,把B格中的数字放入E格,把E格中的数字放入D格,把D格中的数字放入A格。
定义β变换如下:把B格中的数字放入C格,把C格中的数字放入F格,把F格中的数字放入E格,把E格中的数字放入B格。
问:对于给定的布局,可否通过有限次的α变换和β变换变成下面的目标布局:
目标布局:1 2 3
4 5 6
输入
本题有多个测例,每行一个,以EOF为输入结束标志。每个测例的输入是1到6这六个数字的一个排列,空格隔开,表示初始布局ABCDEF格中依次填入的数字。
输出
每个输出占一行。可以转换的,打印Yes;不可以转换的,打印No。
输入样例
1 3 5 2 4 6
2 5 6 4 3 1
输出样例
No
Yes
解析:此题较难,需要用到广搜和队列解决的问题。建议去看一下博主写的算法设计与分析篇的所有文章,虽然可能难度大于机试,但涵盖了所有算法,如分支限界法、回溯法、动态规划等所有高明的算法。下面解析一下本题。
对于输入的序列,可使用一维或者二维数组存下来,以便于后边bfs(广搜函数)在遍历到下一个状态时,用来比较这个状态是否早已经到达。此处我用一维数组存,以便使用map函数。进入bfs后,每次取出队列首的序列,进行两个不同的转换,即α和β变换,变换在外边写函数实现,不要冗杂在bfs里。将变换所得状态入队列,并且步数加一。当然入队列之前检查这一步是否早已被到达,要是早已到达就不用入队列了(早到了你现在才到,当然选步数早的到法),不然就不满足广搜最优性质了。
然后重点来了,那么我们怎么检查当然的状态是否已经用过了呢?队列里的每一步的状态是边用边离开的,以前的状态都没有保存下来,所以我们没办法遍历队列进行比较看是否它用过了。那么这里我们有两种解决办法,第一种是利用C++自带的map函数,可以自带查重的功能,这个大家可以自行查询。第二种是自己的土方法,就是从队列刚开始工作时,就把每一步的状态都存到一个二维数组里,以后的新状态都遍历这个二维数组进行查重。这两种方法都是行得通的。
大概如此,至于更为详尽的解析,参考另一篇博主的:https://mp.csdn.net/editor/html/86256433
代码:
#include<iostream>
#include<string>
#include<map>
#include<queue>
using namespace std;
map<int,int>used;
queue<int>q;
int m[7]={0};
int num=0;
void Readdata()
{
num=0;
for(int i=0;i<6;i++)
{
cin>>m[i];
num=num*10+m[i];
}
}
void Initdata()
{
while(!q.empty())//清空队列
q.pop();
used.clear();//清空map
used[num]=1;//或者used.insert(map<int,int>(num,1)))
q.push(num);//将输入数字入队列和map
}
int Move(int cur,int i)
{
int res=0;
for(int j=5;j>=0;j--)
{
m[j]=cur%10;
cur=cur/10;
}
int a,b,c,d,e,f;
if(i==0)
{
a=m[0];
b=m[1];
d=m[3];
e=m[4];
m[1]=a;
m[4]=b;
m[3]=e;
m[0]=d;
}
else
{
b=m[1];
c=m[2];
e=m[4];
f=m[5];
m[2]=b;
m[5]=c;
m[4]=f;
m[1]=e;
}
for(int j=0;j<6;j++)
res=res*10+m[j];
return res;
}
int bfs()
{
//队列为空为截至条件,要是还是到不了说明无法到达
while(!q.empty())//队列为空为截至条件
{
int cur=q.front();
q.pop();//取出队列首元素
for(int i=0;i<2;i++)
{
int v=Move(cur,i);//分别进行两次转换
if(v==123456)
return 1;
else if(used[v]==0)
{
q.push(v);
used[v]=1;
}
}
}
return 0;
}
int main()
{
while(1)
{
Readdata();
Initdata();
if(bfs())
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
}
return 0;
}