述:大二初一次简单的测试

经过在暑假一个月的学习,大二第一学期开学进行了学习结果测试

(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();
				else
					break;
			}
			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");
		else
			printf("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;
}

因为循环往往是很耗时的,所以可以优化问题,尽可能减少循环嵌套或者直接不用循环;

第三题:

第三道题

第三道题1

英语描述了一大段看着挺吓人的,其实看了一眼输入,输出和这个温馨的提示。就瞬间明白了要求是找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.1415926535897932
using 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  (第一次写的个人博客)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值