2017级寒假ACM集训结训赛--官方题解
博客地址
A:SDUTOJ4142 蚂蚁花呗
AC/SUBMIT : 25/245
by:郭小冉(徐红博)
考查知识点:栈
通过简单的栈模拟,对于向左走的蚂蚁如果没有向右走的蚂蚁直接加入进栈,如果有,则比较大小,向左的蚂蚁大吃掉向右走的蚂蚁(pop),否则是被吃掉。
对于向右走的直接加入栈中。
当然如果暴力的话,姿势好一点的话也可以过,但是由于测题时就有人暴力卡过,所以特意加了一组10000只蚂蚁全是左边的数据,因此卡掉了一部分暴力的做法。
比如下边的这种就正好被卡掉
#include <iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int s[100010],book[100010],b[100010];
int main()
{int t,n,sum,i,j;cin>>t;while(t--){cin>>n;sum=n;memset(book,0,sizeof(book));for(i=0;i<n;i++){cin>>s[i]>>b[i];}for(i=0;i<n;i++){if(b[i]==1) continue;for(j=i-1;j>=0;j--){if(b[j]==0) continue;if(book[j]) continue;
// printf("%d\n",j);if(s[i]>s[j]){sum--;book[j]=1;}if(s[i]<s[j]){book[i]=1;sum--;break;}}}printf("%d\n",sum);}return 0;
}
标程1(c++版):
# include <bits/stdc++.h>
using namespace std;int main()
{int t;scanf("%d",&t);while(t--){stack<int>s;int n, a, b, sum = 0;scanf("%d",&n);for(int i=0; i<n; ++i){scanf("%d%d",&a,&b);if(b == 0){while(!s.empty() && s.top() < a) ++sum, s.pop();if(!s.empty()) ++sum;}elses.push(a);}printf("%d\n",n-sum);}return 0;
}
标程2(c语言版):
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
using namespace std;
int main()
{int t;scanf("%d",&t);int a,b,n;while(t--){int Stack[8124];int top =0,sum =0 ;scanf("%d",&n);for(int i=1; i<=n; i++){scanf("%d%d",&a,&b);if(!b){while(top!=0&&Stack[top-1]<a){++sum;top--;}if(top!=0){++sum;}}else{Stack[top++] = a;}}printf("%d\n",n-sum);}return 0;
}
B:SDUTOJ4143 蚂蚁森林
AC/SUBMIT : 0/10
by:郭小冉(徐红博)
考查知识点:排序+思维
比较考验思维的题目,应该属于这套题中思考难度最大的题目了;加了提示之后也没有人能想到(当然加完提示时剩下的时间已经比较短了)。
每只蚂蚁在木棍上都有自己的相对位置, 如果两只蚂蚁碰头就会改变自己的朝向,所以他们在木棍上的相对位置是不会改变的,给所有蚂蚁的位置标记大小并从小到大排序,设置初始数组和终态数组表示蚂蚁的状态,设置一个order数组表示蚂蚁被放置进去的顺序,在输出结果的时候根据这个顺序输出。
如果还不是很明白的话,可以看下面一组样例感受一下。
比如,有3只蚂蚁,蚂蚁1=(1, R),蚂蚁2= (3, L),蚂蚁3=(4, L),则两秒钟之后,3只蚂蚁分别为 1=(3,R)、2= (1,L)和 3= (2,L), 这是不转向的结果;
按照题意转向的话其结果应该为1=(1, L) , 2=(2, L), 3=( 3, R );即按位置排个序,就是它们对应的新位置;
关键点在于:对于蚂蚁来说, 可以把它们看成是没有区别的小点,那么只需独立计算出每只蚂蚁在T时刻的位置即可;
标程使用了STL中的排序,如果没有学过的同学可以先学习一下再尝试来解决这道题。
标程:
#include<stdlib.h>
#include <algorithm>
#include <stdio.h>
#include<string.h>
using namespace std;
struct node
{int x,dir,id;
} cnt[10007],cnt_ans[10007];
int n,Time,l;
const char name[][10]= {"L","Turning","R"};
int cmp(node a,node b)
{return a.x<b.x;
}
int main()
{int t,tt=0;scanf("%d",&t);while(t--){tt++;printf("Case #%d\n",tt);scanf("%d%d%d",&l,&Time,&n);int t1,t2;char direction[5];for(int i=1; i<=n; i++){scanf("%d %s",&t1,direction);cnt[i].x = t1;cnt[i].id = i;if(direction[0]=='L')cnt[i].dir = -1;else cnt[i].dir = 1;cnt_ans[i].x = t1+Time*cnt[i].dir;cnt_ans[i].dir = cnt[i].dir;cnt_ans[i].id = i;}sort(cnt+1,cnt+1+n,cmp);int id_change[10007]= {0};for(int i=1; i<=n; i++){id_change[cnt[i].id] = i;}sort(cnt_ans+1,cnt_ans+1+n,cmp);for(int i=1; i<=n-1; i++){if(cnt_ans[i].x==cnt_ans[i+1].x){cnt_ans[i].dir = cnt_ans[i+1].dir = 0;}}for(int i=1; i<=n; i++){int yy = id_change[i];if(cnt_ans[yy].x<0||cnt_ans[yy].x>l)printf("Fell off\n");elseprintf("%d %s\n",cnt_ans[yy].x,name[cnt_ans[yy].dir+1]);}printf("\n");}
}
C:SDUTOJ4144 蚂蚁财富
AC/SUBMIT : 3/8
by:郭小冉(徐红博)
考查知识点:思维+模拟
本题的代码不是十分的复杂,但是就思考上来说也有一定的难度,所以在一开始就发了公告提示。
有些人可能觉得可以暴搜,因为每只蚂蚁只有两种情况,不过每只蚂蚁都要掉头是不是很麻烦,而且时间复杂度为2的n次幂,肯定超时。 因为所有蚂蚁是同时出发的,相遇时的两只蚂蚁用的时间是相同的,我们可以无视蚂蚁的区别,当两只蚂蚁相遇时它们保持原样交错而行。这样每只蚂蚁都是独立运动的,那么只要找每只蚂蚁掉下去的时间就行了。
标程:
#include<cstdio>
#define maxn 1000100
int a[maxn],ans,L,n;
int MIN(int a,int b)
{return a<b?a:b;
}
int MAX(int a,int b)
{return a>b?a:b;
}
void ansMIN()
{int i,min;ans=-1;for(i=0; i<n; ++i){min=MIN(a[i],L-a[i]);if(min>ans)ans=min;}printf("%d ",ans);
}
void ansMAX()
{int i,max;ans=-1;for(i=0; i<n; ++i){max=MAX(a[i],L-a[i]);if(max>ans)ans=max;}printf("%d\n",ans);
}
int main()
{int i,t;scanf("%d",&t);while(t--){scanf("%d%d",&L,&n);for(i=0; i<n; ++i)scanf("%d",&a[i]);ansMIN();//求所有蚂蚁掉下去的最短时间ansMAX();//求所有蚂蚁掉下去的最长时间}return 0;
}
D:SDUTOJ4145 蚂蚁借呗
AC/SUBMIT : 18/53
by:郭小冉(徐红博)
考查知识点:dfs搜索|模拟
本题实际上是一个十分裸的搜索题, 但是由于题目要求,因此其实只用循环模拟就可以做,由于题目设计的时候下标从零开始,题目中给出这个条件的位置也不是十分的显眼,因此导致有些人可能在这个地方遇到了坑。但只要能够枚举出八种情况,这道题就能够轻松解决。
利用二维数组模拟方格,读取数据,初始化方格状态,蚂蚁位置等。按照题目思路进行模拟。
知道了蚂蚁在哪,朝向哪,将所在格子颜色反转(!mp[x][y]),下一步就是根据格子原来的颜色转向了,因为提供的方向是英文,如果用switch进行选择不免显得繁琐,所以可以用数字0123来代替上右下左四个方向,蚂蚁转向可以就用取余运算来进行,右转就是 (s+1)%4,左转就是(s+3)%4,然后根据方向移动改变坐标即可。
标程1(搜索版):
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int xx[]={-1,0,1,0};
int yy[]={0,1,0,-1};
int mp[111][111];
void dfs(int x,int y,int pos,int step)
{if(pos==0){printf("%d %d\n",x,y);return ;}int t_step;if(mp[x][y]) t_step=(step+5)%4;else t_step=(step+3)%4;int fx=x+xx[t_step];int fy=y+yy[t_step];mp[x][y]=1-mp[x][y];dfs(fx,fy,pos-1,t_step);
}
int main()
{int t,i,j,n,m;;cin>>t;while(t--){cin>>n>>m;for(i=0;i<n;i++){for(j=0;j<m;j++){scanf("%d",&mp[i][j]);}}int x,y,p,sp;char s[10];scanf("%d%d%s%d",&x,&y,&s,&p);if(s[0]=='U') sp=0;if(s[0]=='D') sp=2;if(s[0]=='L') sp=3;if(s[0]=='R') sp=1;dfs(x,y,p,sp);}return 0;
}
标程2(while循环模拟):
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
int m, n;
int Graph[105][105];
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
int main()
{int t;scanf("%d",&t);while(t--){scanf("%d %d", &m, &n);for(int i = 0; i < m; i++)for(int j = 0; j < n; j++)scanf("%d", &Graph[i][j]);int x, y, k;char s[5];scanf("%d %d %s %d", &x, &y, s, &k);int to; //朝向if(s[0] == 'U') to = 0;else if(s[0] == 'R') to= 1;else if(s[0] == 'D') to= 2;else if(s[0] == 'L') to= 3;while(k){if(Graph[x][y] == 0){if(to == 0) to = 3;else to--;}else{to = (to + 1) % 4;}Graph[x][y] = Graph[x][y]^1;x += dx[to];y += dy[to];k--;}printf("%d %d\n", x, y);}return 0;
}
标程3(枚举八种情况):
#include <stdio.h>
#include <string.h>
int a[100][100];int main()
{int t;scanf("%d",&t);while(t--){int m,n,i,j,x,y,k;char s;memset(a,0,sizeof(a));scanf("%d %d",&m,&n);for(i=0;i<m;i++)for(j=0;j<n;j++)scanf("%d",&a[i][j]);scanf("%d %d %c %d",&x,&y,&s,&k);while(k--){if(s=='U'){if(a[x][y]==1){a[x][y]=0;s='R';y++;}else if(a[x][y]==0){a[x][y]=1;s='L';y--;}}else if(s=='D'){if(a[x][y]==1){a[x][y]=0;s='L';y--;}else if(a[x][y]==0){a[x][y]=1;s='R';y++;}}else if(s=='L'){if(a[x][y]==1){a[x][y]=0;s='U';x--;}else if(a[x][y]==0){a[x][y]=1;s='D';x++;}}else if(s=='R'){if(a[x][y]==1){a[x][y]=0;s='D';x++;}else if(a[x][y]==0){a[x][y]=1;s='U';x--;}}}printf("%d %d\n",x,y);}return 0;
}
E:SDUTOJ4051 巨斧砍大树
AC/SUBMIT : 13/33
by:bLue(刘洋)
考查知识点:树
建立二叉树,然后在删除子树时只要将该子树的根节点置为 NULL 即可
标程:
// by bLue#include <cstdio>
using namespace std;struct node {int data;node *left;node *right;
};bool is_first;node * Build(node *p, int data) {if(!p) {p = new node;p->data = data;p->left = p->right = NULL;}else {if(data < p->data)p->left = Build(p->left, data);elsep->right = Build(p->right, data);}return p;
}node * Delete(node *p, int data) {if(!p) printf("Already cut %d\n", data);else {if(data == p->data) {printf("Cut %d\n", data);p = NULL;}else if(data < p->data)p->left = Delete(p->left, data);elsep->right = Delete(p->right, data);}return p;
}void InorderTraverse(node *p) {if(p) {InorderTraverse(p->left);if(is_first) is_first = false;else printf(" ");printf("%d", p->data);InorderTraverse(p->right);}
}int main(int argc, char const *argv[]) {int n, m, v;node *root = NULL;scanf("%d %d", &n, &m);for(int i=0; i<n; ++i) {scanf("%d", &v);root = Build(root, v);}for(int i=0; i<m; ++i) {scanf("%d", &v);root = Delete(root, v);is_first = true;InorderTraverse(root);printf("\n");}return 0;
}
F:SDUTOJ4146 龙王的工作
AC/SUBMIT : 30/67
by:玄黄(秦圣昭)
考查知识点:思维
实际上,这道题目是作为最简单的签到题的,只要读懂题意,那么这道题目就能够A掉。注意步兵时不移动的。由于玉将每次只能行进一格,那么要想回合数最少肯定是每一步都往步兵行进的方向去走,而但二者差别较远时肯定是斜着走最优,当二者走到同一行或者同一列时,玉将就只能直着走了,也就是说答案其实是两者横纵坐标相减,差别最大的那一个。
code:
#include <stdio.h>
#include <stdlib.h>
#include<math.h>
int max(int a,int b)
{if(a>b)return a;elsereturn b;
}
int main()
{int x1,y1,x,y,max1;while(scanf("%d %d %d %d",&x1,&y1,&x,&y)!=EOF){max1=max(abs(x1-x),abs(y1-y));printf("%d\n",max1);}return 0;
}
G:SDUTOJ4141 唱歌的小P
AC/SUBMIT : 92/404
by:IceCapriccio(王炜良)
考查知识点:模拟
由一开始样例有误,所以可能会有一部分人wa,但是只要老老实实按题目意思模拟,这个题很容易就A掉了。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{char a[1006];while(gets(a)){//getchar();int i;for(i=0;a[i]!='\0';i++){if(a[i]=='B'){printf("D");}else if(a[i]=='D'){printf("B");}else if(a[i]=='P'){printf("B");}else if(a[i]=='Z'){printf("\n");}else if(a[i]==' ');else{printf("%c", a[i]);}}printf("\n");}return 0;
}
H:SDUTOJ2498 数据结构实验之图论十一:AOE网上的关键路径
AC/SUBMIT : 0/3
考查知识点:最短路+拓扑序
大体就是SPFA(最短路贝尔曼算法的优化)逆向建图,然后通过入出度的关系找出原点和汇点,主要是将关键路径上的点输出,用一个pre数组记录,所求的最长路上的各个点。且值为上一节点,下标为下一节点。然后将pre数组所描述的路径,通过另一个数组
存下来,输出即可。
标程1:
#include<bits/stdc++.h>
using namespace std;
struct edge{
int v,w,pre;
}p[55555];int n,m,next[10086],head[10086],cnt,vis[10086],dis[10086],i,u,v,w;
int main()
{while(~scanf("%d%d",&n,&m)){memset(head,-1,sizeof(head));memset(next,0,sizeof(next));memset(vis,0,sizeof(vis));memset(dis,0,sizeof(dis));cnt=0,vis[n]=1;for(i=0;i<m;i++){scanf("%d%d%d",&v,&u,&w);p[cnt].v=v,p[cnt].w=w,p[cnt].pre=head[u],head[u]=cnt++;}queue<int>q;q.push(n);while(!q.empty()){u=q.front();q.pop();vis[u]=0;for(i=head[u];~i;i=p[i].pre)if(dis[p[i].v]<dis[u]+p[i].w||(dis[p[i].v]==dis[u]+p[i].w&&next[p[i].v]>u)){dis[p[i].v]=dis[u]+p[i].w,next[p[i].v]=u;if(!vis[p[i].v]){q.push(p[i].v);vis[p[i].v]=1;}}}printf("%d\n",dis[1]);for(i=1;next[i];i=next[i])printf("%d %d\n",i,next[i]);
}
return 0;
}
标程2:
#include <bits/stdc++.h>
using namespace std;
const int Inf = 0x3f3f3f3f;
struct node {int v;int w;int next;
}edge[50004];
queue <int> que;
int cnt, head[10004], dis[10004], vis[10004];
int pre[10004], in[10004], out[10004];
int num, ans[10004];void Add(int u, int v, int w);
void spfa(int s, int e, int n);int main(){int n, m, i, u, v, w;while(scanf("%d %d", &n, &m) != EOF){cnt = 0;memset(head, -1, sizeof(head));memset(in, 0, sizeof(in));memset(out, 0, sizeof(out));while(m--){scanf("%d %d %d", &u, &v, &w);Add(v, u, w);in[u]++, out[v]++;}for(i = 1; i <= n; i++){if(!in[i])u = i;if(!out[i])v = i;}spfa(u, v, n);}return 0;
}
void Add(int u, int v, int w){edge[cnt].v = v;edge[cnt].w = w;edge[cnt].next = head[u];head[u] = cnt++;
}
void spfa(int s, int e, int n){int i, u, v;memset(dis, -Inf, sizeof(dis));memset(pre, Inf, sizeof(pre));memset(vis, 0, sizeof(vis));while(!que.empty()){que.pop();}que.push(s);dis[s] = 0;vis[s] = 1;while(!que.empty()){u = que.front();que.pop();vis[u] = 0;for(i = head[u]; ~i; i = edge[i].next){v = edge[i].v;if(dis[v] < dis[u] + edge[i].w || (dis[v] == dis[u] + edge[i].w && u < pre[v])){dis[v] = dis[u] + edge[i].w;pre[v] = u;if(!vis[v]){vis[v] = 1;que.push(v);}}}}printf("%d\n", dis[e]);num = 0;for(i = e; i != Inf; i = pre[i])ans[num++] = i;for(i = 1; i < num; i++)printf("%d %d\n", ans[i-1], ans[i]);
}
2017级寒假ACM集训结训赛--官方题解相关推荐
- 北京信息科技大学第十三届程序设计竞赛暨ACM选拔赛(重现赛)题解
题目链接: 北京信息科技大学第十三届程序设计竞赛暨ACM选拔赛(重现赛)_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ大学ACM校赛新生赛是面向ACM/ICPC/CCP ...
- 蓝桥杯2017第八届C语言B组省赛习题题解——习题I.分巧克力
儿童节那天有K位小朋友到小明家做客.小明拿出了珍藏的巧克力招待小朋友们. 小明一共有N块巧克力,其中第i块是Hi x Wi的方格组成的长方形. 为了公平起见,小明需要从这 N 块巧克力中切出K块巧克力 ...
- 第十二届西南石油大学程序设计新生赛官方题解
整理的算法模板合集: ACM模板 目录 A.杰杰国王的平等节(easy)[签到] B.最佳复习效果(easy - mid)[二分查找] C.无限之路(mid - hard)[离散化+前缀和] D.Is ...
- 2017年山东省ACM省赛总结
2017年山东省ACM省赛总结 ----但求努力到问心无愧 这次比赛我们是作为友谊队去的,本来我们队选拔赛成绩并不是很好,是去不了的,但伟大的教主大人牛逼地又要到了几个省赛友谊队的名额,才让我们有这次 ...
- 北邮计算机学院学生会军训,在北京邮电大学2015级本科生军训结训典礼上的讲话...
2015年9月25日在北京邮电大学2015级本科生军训结训典礼上的讲话 乔建永 校长 各位教官.老师们,同学们: 今天,我们在这里隆重举行2015级本科生军训结训典礼.我谨代表学校向圆满完成军训任务 ...
- 【ECJTU_ACM 11级队员2012年暑假训练赛(8) - F - A Mame】
Home Problems Status Contest Register Login B题要套一个数论的模版,注意m=1!! C题可以二分匹配,把行列看作点; 不能开百度,开谷歌搜题解,再次强调!一 ...
- “师创杯”山东理工大学第九届ACM程序设计竞赛 正式赛 F.校赛~校赛~【思维+规律题】
校赛~校赛~ Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Problem Description SDUT 的校赛是从 20 ...
- java基础面试题题库五(传智专修学院2017级Java4班)
------------------------------------------------------------- 本面试题由传智专修学院2017级java4班所有同学合作完成 ------- ...
- ACM新生赛部分题解
2021级的ACM新生赛已经完结了,我就自己做出来的八道题整理一下题解,因为其他是真的不会. 链接:登录-专业IT笔试面试备考平台_牛客网 来源:牛客网 一.我们是冠军 7 日星期 777 的凌晨,7 ...
最新文章
- Blender 3.0机器人硬面建模材质渲染全流程学习课程
- 一种新的计算机视觉技术?将手机的摄像头变成了一个搜索引擎
- 软件架构设计-五视图方法论
- oracle protocol=beq 不可用,Oracle BEQ方式连接配置
- php 自增,php 根据自增id创建唯一编号类
- 前端传值后端接收不到_解决vue get请求传参后端接收不到参数值(java sptingboot)
- VTK:可视化算法之CutWithCutFunction
- CentOS 6.3 下编译Nginx(笔记整理)
- java volidate线程安全_03.(多线程与并发)面试题-02--Volidate的原理和指令重排序
- Golang时间格式化
- SpringBoot 嵌入式web容器的启动原理
- 【国产化电脑】如何有效避免违规外联
- 如何批量将 Word 文档转为 PDF 格式
- Python爬取网易车型库
- IntelliJ IDEA 整理代码格式 快捷键
- “人活着是为了什么?”“生活的中心是什么?”
- html椭圆的写法,4.8 把圆变换为椭圆 - HTML5 Canvas 实战
- 1404111-67-6,N-Boc-PEG5-alcohol,N-Boc-PEG5-CH2CH2OH实验室常用试剂的保存方法
- 图片展示(上面一个大图下面四个小图)
- 降维 (Dimensionality Reduction)