述:大二初一次简单的测试
来源:互联网 发布:淘宝网儿童棉睡衣 编辑:程序博客网 时间:2024/06/03 02:09
经过在暑假一个月的学习,大二第一学期开学进行了学习结果测试
(2017.9.26 周二下午三点到七点的测试,中午睡过了,影响了半个小时的时间,没有抢到先机有点尴尬。。。)
一共有六道题,没有具体难度区分;来的时候比较紧急大概浏览了一边,发现第一题的括号配对和第四题的会场安排都在暑假的时候做过了;有一道英文题(因为英语水平不高,心中暗道还好还好)心情也由来晚稍稍放松了一点,先拿到第一题就开始做了。
先来说说题目吧:
第一题:
从题目来看是对于数据结构的简单应用,栈的push(放入),top(顶部元素),pop(丢掉);遵循先进后出的原则进行处理数据;
所以就可以把问题简单化,左括号直接放入栈中,右括号则进行if判断,如果满足于栈的top(顶)结合,然后就pop(把栈顶的元素丢掉);
有了基本思路就开始着手打代码;
#include<iostream>#include<stack>#include<cstdio>#include<cstring>using namespace std;int main(){char k[110];int m,i,n;scanf("%d", &m);while (m--){scanf("%s", k); n = strlen(k); int h = 0;stack <char>s; s.push('#');if (n == 0 || n % 2 != 0)h = 1;else{ for (i = 0; i < n; i++){if (k[i] == '(' || k[i] == '[' || k[i] == '{' || k[i] == '<'){s.push(k[i]);}else if (k[i] == ')'){if (s.top() == '(')s.pop();elsebreak;}else if (k[i] == ']'){if (s.top() == '[')s.pop();else break;}else if (k[i] == '}'){if (s.top() == '{')s.pop();else break;}else if (k[i] == '>'){if (s.top() == '<')s.pop();else break;}}}if(h!=0) printf("No\n");else if (s.top() == '#')printf("Yes\n");elseprintf("No\n");}return 0;}
是不是看着太麻烦了,这是当时自己做的,后来发现其实else if 就是不需要的,增加了代码的长度并减少了可阅读性;
而且这样分段写,需要多注意的是在考虑了左括号直接压入栈后是可以正常计算,但是一开始的是右括号呢,一直都是右括号的情况,我就疏忽了这个(好像当时还没睡醒,有点迷迷糊糊的)直道提交了四次才意识到,真的失误了,有了教训其他的都是一边过的。
还是学长的答案看着比较舒服。。。 来分享一下:
#include <cstring>#include <cstdio>#include <stack>char s[10005];int main(){ int n; scanf("%d", &n); while (n--) { int len, i; std::stack <char> c; scanf("%s", s); len = strlen(s); for (int i = 0; i < len; i++) { if (c.empty()) c.push(s[i]); else { if((s[i]==')'&&c.top()=='(')||(s[i]==']'&&c.top()=='[') || (s[i]=='>'&&c.top()=='<') || (s[i]=='}'&&c.top()=='{')) c.pop(); else c.push(s[i]); } } if (!c.empty()) printf("No\n"); else printf("Yes\n"); }}
思路是一样的,但是在处理右括号的方面有了很大的改进,把逐句判断写成了同步判断然后||语句链接,把所有情况都考虑了进去。还是比较厉害的,对于新手的我来说很值得借鉴学习。
第二题:
做这道题的关键就是看清题,看清题!!! 清楚了怎么分给下个人的那么这题是很简单的。 是每个人同时去除一半然后同时给右边的那位,把最后一位单一考虑就可以了。
当时好像浪费了一个小时在看错题上了,已知数据不过才仔细看题意识到,不是拿了给右边的,然后右边的再拿出现有的一半给右边的朋友; 唉,这两道满满的累,拖了好长时间才搞定,本来很简单的两道题,细心才是最重要的。
#include<stdio.h>#include<string.h>int k[10001],t[10001],n,sum;int fun(){int i,max=k[0];for(i=0;i<n;i++) { if(k[i]!=max) return 0;} return 1;}int main(){int i,max;while(~scanf("%d",&n)){if(n==0) break;sum=0;for(i=0;i<n;i++){scanf("%d",&k[i]);} if(fun()) printf("%d %d\n",sum,k[0]);else{while(1){for(int i=0;i<n;i++){t[i]=k[i]/2;k[i]=k[i]/2;}for(int i=1;i<n;i++){k[i]=k[i]+t[i-1];if(k[i]%2!=0) k[i]=k[i]+1;} k[0]=t[n-1]+k[0]; if(k[0]%2!=0) k[0]=k[0]+1;sum++;if(fun())break;}printf("%d %d\n",sum,k[0]);sum=0;memset(k,0,n+1);}}return 0; }
代码写得复杂了,因为一直是在原先想错方向之后改正的,直接加了一个数组来存放每位朋友拿出来的一半,每次循环都作出更新。
还好测试数据不大就直接过了;
看看学长写的做下比较:
#include <cstdio>#include <cstring>int children[105];int main(){ int n; while (scanf("%d", &n) && n) { memset(children, 0, sizeof(children)); for (int i = 0; i < n; i++) { scanf("%d", &children[i]); } int cnt = 0; while (true) { bool flag = false; int dot; for (int i = 0; i < n - 1; i++) { if (children[i] != children[i + 1]) { flag = true; break; } } if (!flag) { break; } cnt++; int sweet = children[0] / 2; for (int i = 0; i < n; i++) { //这里可以优化一下 想想怎么优化。 children[i] /= 2; if (i != n - 1) { children[i] += children[i + 1] / 2; } else { children[i] += sweet; } } for (int i = 0; i < n; i++) { if (children[i] % 2) children[i]++; } } printf("%d %d\n", cnt, children[0]); } return 0;}
因为循环往往是很耗时的,所以可以优化问题,尽可能减少循环嵌套或者直接不用循环;
第三题:
英语描述了一大段看着挺吓人的,其实看了一眼输入,输出和这个温馨的提示。就瞬间明白了要求是找10000以内所有满足提示所展示的数字 等于另一个数字的各位数字和本身的和; 若是这样正向找的话,估计又要好多循环开始挨个查找。 所以看到这里不如反向的想想,各位数字和本身相加得到的一位数字记下来就是满足selfs number的;
而这道题就可以用一个10000的数组下标来记录已经找到的,然后用循环输出没有标记的就是答案了;
#include<stdio.h>int k[10005]={0};int main(){int i,j,m,n;for(i=0;i<10000;i++){j=i+i%10+i/10%10+i/10/10%10+i/10/10/10%10;k[j]=1;}for(i=0;i<10000;i++){if(k[i]==0) printf("%d\n",i);}}
做这道题想到了nyoj上的 无主之地 方法比较类似
虽然自己的这个已经有点自信了,看到学长的更加简洁;
#include<cstdio> #include<cstring> using namespace std; int num[20010]; int main() { int i,j,k; for(i=1;i<=10000;i++) { num[i/1000+i/100%10+i/10%10+i%10+i]=1; if(!num[i]) printf("%d\n",i); } }
第四题:
这道题考察的就是贪心算法了,很常见的一道;在暑假的时候也做过类似的;简化为区间覆盖问题,利用结构体,把左右端点整体都存下来,然后按左端点排序,若左端点相同则按右端点升序排列;实现还是比较简单的:
#include<iostream>#include<algorithm>#include<stdio.h>using namespace std;struct node{int x,y;}; bool fr(node a,node b){return a.x==b.x?a.y<b.y:a.x<b.x;}int main(){int m,n,i,sum,p;struct node k[10010];scanf("%d",&m);while(m--){scanf("%d",&n);for(i=0;i<n;i++){scanf("%d%d",&k[i].x,&k[i].y);}sort(k,k+n,fr);p=k[0].y;sum=1;for(i=1;i<n;i++){if(k[i].x>p){sum++;p=k[i].y;}else if(k[i].y<p){p=k[i].y;}}printf("%d\n",sum);}}
想想当时刚开始接触贪心的时候可是熬夜通宵打一道题,还是熟能生巧比较实在;
看看学长的代码,这次在排序代码的简洁上略微有点优势哦(笑笑。。哈哈哈)
#include <cstdio>#include <algorithm>using namespace std;struct Time{ int a; int b;};struct Time s[10010];int compare(struct Time a, struct Time b){ if(a.b != b.b){ return a.b < b.b; } return a.a < b.a;}int main(){ int n, t, i, j, k, ans, end; scanf("%d", &t); for(i=1; i<=t; i++){ scanf("%d", &n); for(j=0; j<=n-1; j++){ scanf("%d%d", &s[j].a, &s[j].b); } ans=0; end=-1; sort(s, s+n, compare); for(j=0; j<=n-1; j++){ if(s[j].a>end){ ans++; end=s[j].b; } } printf("%d\n", ans); } return 0;}
第五题:
这道题用到了贪心+二分法;贪心找最大方案,寻找工具是二分查找(由于数据较大而且精度较高,二分不会超时,而且贪心和二分是很好的组合~)
先明白题目的意思:把已知大小的蛋糕分给若干人,要取得最大化,把最大的一块蛋糕先找出来,当作二分的右边界,左边界初始为0,把中值当作此时要分的蛋糕最大值,看是否符合人数需要,若是满足,则把左值右移到中值,扩大中值,以此类推找到最合适的中值,也就是最大的蛋糕分配;(附:PI = 3.1415926535897932)
#include<stdio.h>#include<algorithm>#define PI 3.1415926535897932using namespace std;int n,f; double v[10005];bool fun(double mid){int m=0;double a;for(int i=n-1;i>=0;i--) { a=v[i]; while(a>=mid) { a=a-mid; m++;}}if(m>=f) return true; else return false;}int main(){int i,m;double a;scanf("%d",&m);while(m--){scanf("%d%d",&n,&f);f++;for(i=0;i<n;i++){scanf("%lf",&a);v[i]=a*a*PI;}sort(v,v+n);double l=0,r=v[n-1],mid;while(r-l>=0.00000001){mid=(l+r)/2;if(fun(mid)) l=mid;else r=mid;}printf("%.4lf\n",mid);}return 0;}
这个是考试完写的了,前面用的时间太久了; 看看学长的代码:
#include<iostream>#include <cstdio>using namespace std;const double PI = 3.1415926535897932;const int MAXN = 1005;const double ESP=1e-6;double v[MAXN];int main(void){ int test; cin>>test; while(test--) { int n,f; cin>>n>>f; f++; double maxsize = 0.0; for(int i=1;i <= n;i++) { cin >> v[i]; v[i] *= v[i]; if( maxsize < v[i]) maxsize = v[i]; } double low = 0.0; double high = maxsize; double mid; while(high - low > ESP) { mid = (low + high) / 2; int count_f = 0; for(int i = 1; i <= n; i++) count_f += (int)(v[i] / mid); //当前半径下,每一块蛋糕可以分成几份 if(count_f < f) high = mid; //因为求的是高精度的小数 所以high最好是等于mid,我试过high=mid+ESP,提交错误,应该是ESP的精度太小的原因。 else low = mid; } printf("%.4lf\n", mid * PI); } return 0;}
没有调用函数,而是直接写到了循环体里面;看着更加方便了一些;
第六题:
这道题用到了深搜,可是我还不会,也没写出来,就先附上学长的代码,等会了再来补充吧。
#include<iostream>#include<cstdio>#include<cstring>using namespace std;const int maxn=10;char board[maxn][maxn];int isPut[maxn]; //判断某一列是否可以放棋子 int n,k;int cnt,num; //cnt方案数 num 棋子数 void DFS(int i){ if(k==num){ cnt++; return ; } if(i>=n) return ; for(int j=0;j<n;j++) if(!isPut[j] && board[i][j]=='#'){ isPut[j]=1; num++; DFS(i+1); isPut[j]=0; //回溯,DFS很重要的一步 num--; } DFS(i+1);}int main(){ int i,j; while(scanf("%d%d",&n,&k) && (n != -1 && k != -1)){ //getchar(); for(i=0;i<n;i++){ for(j=0;j<n;j++) //scanf("%c",&board[i][j]); //getchar(); cin >> board[i][j]; } memset(isPut,0,sizeof(isPut)); cnt=0; num=0; DFS(0); printf("%d\n",cnt); } return 0;}
2017.9.27 (第一次写的个人博客)
- 述:大二初一次简单的测试
- 我的初一老师
- 初一-最好的时代
- 初一
- 对这十来天生活的简单思考(大二暑假)
- 一个简单的工资管理程序(大二,无界面)
- 简单的排名次问题
- 一个字符串拷贝的百万次测试
- 我的大学---大二
- 大二的暑假生活
- 大二女生的感慨
- 大二的生活
- 大二的生活
- 大二的生活
- 我的大二生活
- 大二学生的迷惑
- 大二最后的时光
- 迷茫的大二学生
- 网络连接设备
- elasticsearch批量删除数据
- Android中跨进程通信的几种方式
- Spring注解@Profile与@Conditional
- 关于在vmware中安装centos虚拟机
- 述:大二初一次简单的测试
- Codis源码解析——sentinel的重同步(1)
- 数据库操作的注意事项
- python中__str__()函数的用法
- PLSI主题模型
- BZOJ 1724: [Usaco2006 Nov]Fence Repair 切割木板 堆
- TCP/IP (一) ---- 网络协议
- Mybatis随笔
- 如何利用计算机视觉技术来制作科幻电影中酷炫的透明触摸屏