计算机
Problem A 二进制
题目描述:
输入 32 位的二进制 01 串,输出这个数+1 和+3 后的 32 位二进制串
输入描述:
先输入 T,表示输入的组数
然后输入 T 行二进制串
输出描述:
输出+1 和+3 后的二进制串
输入样例:
2
00000000000000000000000000000000
00000000000000000000000000000001
输出样例:
00000000000000000000000000000001
00000000000000000000000000000011
00000000000000000000000000000010
00000000000000000000000000000100
#include <bits/stdc++.h>
#define max 50000
using namespace std;
int main(){
int n;
while(scanf("%d",&n)!=EOF){
for(int i=0;i<n;i++){
char str[32];
scanf("%s",str);
//+1
int c=1;
for(int i=31;i>=0;i--){
int tmp=str[i]-'0'+c;
str[i]=tmp%2+'0';
c=tmp/2;
}
printf("%s\n",str);
c=1;
for(int i=30;i>=0;i--){
int tmp=str[i]-'0'+c;
str[i]=tmp%2+'0';
c=tmp/2;
}
printf("%s\n",str);
}
}
return 0;
}
Problem B. 二叉树
题目描述
对二叉树,计算任意两个结点的最短路径长度。
输入
第一行输入测试数据组数T
第二行输入n,m 。n代表结点的个数,m代表要查询的数据组数
接下来n行,每行输入两个数,代表1~n结点的孩子结点,如果没有孩子结点则输入-1.根节点为1.
接下来m行,每行输入两个数,代表要查询的两个结点
输出
每组测试数据输出m行,代表查询的两个结点之间的最短路径长度
测试样例
输入
1
8 4
2 3
4 5
6 -1
-1 -1
-1 7
-1 -1
8 -1
-1 -1
1 6
4 6
4 5
8 1
输出
2
4
2
4
我是采用图的求最短路径
#include <bits/stdc++.h>
#define inf 0x7fffffff
using namespace std;
struct point{
int data,dist;
point(int data,int dist):data(data),dist(dist) {}
bool operator < (const point &x) const{
return dist>x.dist;
}
};
int dis[100];
vector<int> graph[100];
void dijsktra(int s,int n){
fill(dis+1,dis+n+1,inf);
priority_queue<point> pq;
dis[s]=0;
pq.push(point(s,dis[s]));
while(!pq.empty()){
int cur=pq.top().data;
pq.pop();
for(int i=0;i<graph[cur].size();i++){
int next=graph[cur][i];
if(dis[next]>dis[cur]+1){
dis[next]=dis[cur]+1;
pq.push(point(next,dis[next]));
}
}
}
}
int main(){
int t,n,m;
for(scanf("%d",&t);t--;){
scanf("%d%d",&n,&m);
memset(graph,0,sizeof(graph));
for(int i=1;i<=n;i++){
for(int j=0;j<2;j++){
int x;
scanf("%d",&x);
if(x!=-1){
graph[i].push_back(x);
graph[x].push_back(i);
}
}
}
//测试图建立正确与否
// for(int i=1;i<=n;i++){
// printf("%d->",i);
// for(int j=0;j<graph[i].size();j++)
// printf("%d ",graph[i][j]);
// printf("\n");
// }
for(int i=0;i<m;i++){
int s,e;
scanf("%d%d",&s,&e);
dijsktra(s,n);
//测试dis数组是否正确
// for(int j=1;j<=n;j++)
// printf("%d ",dis[j]);
printf("%d\n",dis[e]);
}
}
return 0;
}
题目即求最近公共节点,开辟记录父节点的数组
#include <bits/stdc++.h>
using namespace std;
int main(){
int t,n,m,tree[100],l,r,x,y;
for(scanf("%d",&t);t--;){
scanf("%d%d",&n,&m);
tree[1]=-1;
for(int i=1;i<=n;i++){
scanf("%d%d",&l,&r);
if(l!=-1) tree[l]=i;
if(r!=-1) tree[r]=i;
}
while(m--){
stack<int> vx,vy;
scanf("%d%d",&x,&y);
while(tree[x]!=-1){
vx.push(x);
x=tree[x];
}
while(tree[y]!=-1){
vy.push(y);
y=tree[y];
}
while(!vx.empty()&&!vy.empty()){
if(vx.top()==vy.top()){
vx.pop();
vy.pop();
}else{
break;
}
}
printf("%d\n",vx.size()+vy.size());
}
}
return 0;
}
参考了大佬的代码,简化了代码。
Problem C.最短路径
题目描述
在白天和黑夜要从城市1到城市n,黑夜会关掉若干条线路,分别寻找城市1到城市n的在白天和黑夜的最短路径。
输入
第一行数据组数T
第二行输入n,m,k. n代表城市数,m代表路径数,k代表夜间关闭的路径数
接下来m行,每行输入三个数x,y,val,代表城市x和城市y之间连通的距离为val
最后一行k个数,代表晚上关闭的线路序号(线路序号指的是1~m)
感谢补充:不保证无重边,这是考试时,后来补发的公告,所以这题a出的人很少也有这个原因
输出
每组数据输出两行,分别代表白天和黑夜,城市1到n的最短路径
测试样例
1
4 4 1
1 2 1
2 3 1
3 4 1
1 4 1
4
输出
1
3
只写了白天有重复边的情况
#include <bits/stdc++.h>
#define inf 0x7fffffff
using namespace std;
struct edge{
int to,len;
edge(int to,int len):to(to),len(len) {}
};
struct point{
int data,dist;
point(int data,int dist):data(data),dist(dist) {}
bool operator < (const point &x) const{
return dist>x.dist;
}
};
int dis[100];
vector<edge> graph[100];
void dijsktra(){
priority_queue<point> pq;
dis[1]=0;
pq.push(point(1,0));
while(!pq.empty()){
int cur=pq.top().data;
pq.pop();
for(int i=0;i<graph[cur].size();i++){
edge next=graph[cur][i];
if(dis[next.to]>dis[cur]+next.len){
dis[next.to]=dis[cur]+next.len;
pq.push(point(next.to,dis[next.to]));
}
}
}
}
int main(){
int t,n,m,k;
for(scanf("%d",&t);t--;){
scanf("%d%d%d",&n,&m,&k);
fill(dis+1,dis+n+1,inf);
memset(graph,0,sizeof(graph));
while(m--){
int x,y,len;
scanf("%d%d%d",&x,&y,&len);
bool flag=true;
for(int i=0;i<graph[x].size();i++){
if(graph[x][i].to==y&&graph[x][i].len>len){
graph[x][i].len=len;
graph[i][x].len=len;
flag=false;
}
}
if(flag){
graph[y].push_back(edge(x,len));
graph[x].push_back(edge(y,len));
}
}
while(k--){
int num;
scanf("%d",&num);
}
dijsktra();
printf("%d\n",dis[n]);
for(int i=0;i<m;i++){
int s,e;
scanf("%d%d",&s,&e);
for(int j=1;j<=n;j++)
printf("%d ",dis[j]);
printf("%d\n",dis[e]);
}
}
return 0;
}
Problem_A(牙膏问题):
4只牙膏比较价格,返回最便宜的牙膏
输入:
第一行输入T,表示数据的组数
第二行输入a b c d 表示4只牙膏的价格
2
2 3 5 2
3 8 7 4
输出:
2
3
#include <bits/stdc++.h>
using namespace std;
int main(){
int t,num[4];
for(scanf("%d",&t);t--;){
for(int i=0;i<4;i++)
scanf("%d",&num[i]);
sort(num,num+4);
printf("%d\n",num[0]);
}
return 0;
}
Problem_B(闰年问题):
统计连个年份间能被4整除且不能被100整除的普通闰年和能被400整除的世纪闰年的年数
输入:
第一行输入T,表示数据的组数
之后输入T组数据,每组输入x y代表始末年份(y<x)
2
2999 3019
1999 2019
输出:
4
5
#include <bits/stdc++.h>
using namespace std;
bool isrun(int y){
return ((y%4==0&&y%100!=0)||y%400==0)?true:false;
}
int main(){
int t,num[4];
for(scanf("%d",&t);t--;){
int x,y,cnt=0;
scanf("%d%d",&x,&y);
for(int i=x;i<=y;i++){
if(isrun(i)) cnt++;
}
printf("%d\n",cnt);
}
return 0;
}
Problem_C(链表操作):
一个出值为 1,2,3,4,…,n的n(0<n<=50)个节点的顺序链表,有以下3种操作方式:
1 移除节点值为x的节点
2 翻转链表,对调整个链表的顺序
3 查询链表值为x的节点所指的下一个节点的值
输入:
第一行输入T,表示数据的组数
每组第一行输入 n (表示节点数目) m (表示操作数目)
接下来m行分别输入 ope (操作方式) x (操作的节点值,操作方式为2时不会输入该值)
1
6 6
3 6
1 2
3 1
2
1 5
3 6
输出:
输出操作为3查询时,所查节点所指的下一个节点值,若没有查到或查到的节点为表尾 (没有下一节点),输出"NONE"
NONE
3
4
对vector翻转:reverse(v.begin(),v.end())
删除vector的i位:v.erase(v.begin()+i)
#include <bits/stdc++.h>
using namespace std;
int main(){
int t;
vector<int> v;
for(scanf("%d",&t);t--;){
v.clear();
int n,m,op,num;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
v.push_back(i);
while(m--){
scanf("%d",&op);
if(op==2){
reverse(v.begin(),v.end());
}else{
bool flag=false;
scanf("%d",&num);
for(int i=0;i<v.size();i++)
if(v[i]==num){
if(op==1){
v.erase(v.begin()+i);
break;
}
else if(i<v.size()-1){
printf("%d\n",v[i+1]);
flag=true;
break;
}
}
if(op==3&&!flag) printf("NONE\n");
}
for(int i=0;i<v.size();i++)
printf("%d ",v[i]);
printf("\n");
}
}
return 0;
}
Problem_D(网络连接prim):
有一个保证能联通的计算机网络(连通图),
Aij表示i计算机联通到j计算机的开销,
保证 :Aii = 0 , Aij = Aji ,Aij <= 100;
输入:
第一行输入T (T=1),表示数据的组数
每组第一行输入N (0 < N <= 50),表示网络内计算机的数目
然后n行输入Ai0 - Ai n-1
1
6
0 1 4 3 7 3
1 0 2 5 1 8
4 2 0 3 9 2
3 5 3 0 1 4
7 1 9 1 0 3
3 8 2 4 3 0
输出:
返回连通这个计算机网络需要的最小开销
7
其实就是求最小生成树
#include <bits/stdc++.h>
using namespace std;
struct edge{
int cost;
int x,y;
edge(int cost,int x,int y):cost(cost),x(x),y(y) {}
bool operator < (const edge &x) const{
return cost>x.cost;
}
};
int tree[51];
int gettree(int x){
if(x!=tree[x]) tree[x]=gettree(tree[x]);
return tree[x];
}
bool nounion(int x,int y){
x=gettree(x);
y=gettree(y);
if(x!=y){
tree[x]=y;
return true;
}
return false;
}
int main(){
int t,n,num[51][51];
for(scanf("%d",&t);t--;){
scanf("%d",&n);
priority_queue<edge> pq;
for(int i=0;i<n;i++){
tree[i]=i;
}
for(int i=0;i<n;i++)
for(int j=0;j<n;j++){
scanf("%d",&num[i][j]);
if(j>i){
pq.push(edge(num[i][j],i,j));
pq.push(edge(num[i][j],j,i));
}
}
int ans=0;
while(!pq.empty()){
edge e=pq.top();
pq.pop();
if(nounion(e.x,e.y)){
ans+=e.cost;
}
}
printf("%d\n",ans);
}
return 0;
}