寒假第一次周报-------vj算法题

B-上车上车

【问题描述】

公共汽车从始发站(称为第1站)开出,在始发站上车的人数为a,然后到达第2站,在第2站有人上、下车,但上、下车的人数相同,因此在第2站开出时(即在到达第3站之前)车上的人数保持为a人。从第3站起(包括第3站)上、下车的人数有一定的规律:上车的人数都是前两站上车人数之和,而下车人数等于上一站上车人数,一直到终点站的前一站(第n-1站),都满足此规律。现给出的条件是:共有n个车站,始发站上车的人数为a,最后一站下车的人数是m(全部下车)。试问从x站开出时车上的人数是多少?

【输入】

只有一行,四个整数a,n,m和x

【输出】

x站开出时车上的人数

【样例输入】

5 7 32 4

【样例输出】

13
思路:
首先根据题目所描述的情况,随便举一个例子,把每一站的上下车的人数的情况列出来,发现从第五站开始,车上增加的人数是前两站车上增加的人数之和,这时就觉得和斐波那契数列有点类似,但是这里有一个未知数,就是不知道第二站的时候上了多少人或下了多少人,那么可以设为y,让y从0开始一直递增,直到y的值符合用例跳出循环。


#include<stdio.h>
int f(int a,int n,int y)
{
	if(n==1)
	return a;
	else if(n==2)
	return 0;
	else if(n==3)
	return a;
	else if(n==4)
	return y;
	else if(n>=5)
	return f(a,n-1,y)+f(a,n-2,y);
}
int main()
{
	int a,n,m,x,sum=0,i=1;
	scanf("%d %d %d %d",&a,&n,&m,&x);
	int y;
	for(y=1;;y++)
	{
		sum=0;
	    for(i=1;i<n;i++)
		{
		  sum=sum+f(a,i,y);
	    }
	    if(sum==m)
	    break;
	}
	sum=0;
	for(i=1;i<=x;i++)
	{
		sum=sum+f(a,i,y);
	}
	printf("%d",sum);
}

启发:涉及到未知数时直接让其从零一直增,直到符合情况时跳出循环,确定未知数的值。

D-扔盘子

有一口井,井的高度为N,每隔1个单位它的宽度有变化。现在从井口往下面扔圆盘,如果圆盘的宽度大于井在某个高度的宽度,则圆盘被卡住(恰好等于的话会下去)。

盘子有几种命运:1、掉到井底。2、被卡住。3、落到别的盘子上方。

盘子的高度也是单位高度。给定井的宽度和每个盘子的宽度,求最终落到井内的盘子数量。

如图井和盘子信息如下:

井:5 6 4 3 6 2 3

盘子:2 3 5 2 4

最终有4个盘子落在井内。

Input
第1行:2个数N, M中间用空格分隔,N为井的深度,M为盘子的数量(1 <= N, M <= 50000)。 第2 ~ N+1行,每行1个数,对应井的宽度Wi(1 <= Wi <= 10^9)。 第N+2 ~ N+M+1行,每行1个数,对应盘子的宽度Di(1 <= Di <= 10^9)
Output
输出最终落到井内的盘子数量。
Sample Input
7 5
5
6
4
3
6
2
3
2
3
5
2
4
Sample Output
4
分析:刚开始对题目理解不透彻。如果有大盘子落不下去卡在井中间,后面的有的比井口小的盘子也有可能落不下去(盘子堆的太多从井口“溢出”),所以可以将井口变成从上到下缩小的(遍历井口,遇到上层小于下层的情况,将下层变成和上层一样的大小,因为如果上层可以过,那么下层如果和上层一样大也可以过,若过不了,那下层多大都过不了)

#include <stdio.h>
int main()
{
	int a[100000];
    int b[100000];
    int n, m, ans = 0,i,j;
    scanf("%d%d", &n, &m);
    for(i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
        if(i > 1 && a[i] > a[i - 1]) 
		a[i] = a[i - 1];
    }
    for(i = 1; i <= m; i++)
    {
        scanf("%d", &b[i]);
    }
    for(i = n, j = 1; i >= 1; i--)
    {
        while(a[i] < b[j] && i >= 1) i--;
        if(a[i] >= b[j])ans++;
        j++;
    }
    printf("%d", ans);
}

J-发麻将喽

·每个人都有一个自己的分数a,代表本次比赛中获得的成绩。·每个选手至少可以获得1张麻将作为奖励。
·如果两位选手站位相邻,积分高的选手一定比积分低的选手获得的麻将多。
lnput
输入数据共2行,第一行包括一个整数n(1 ≤n ≤ 105)。
接下来n行,每行1个整数a1 , a2,… , an(1<a ≤105),其中第i个数表示站在第i位的人的积分。
输出共一行,表示主裁判汪次郎最少发的麻将数。
Example
Input
3
1
2
2
Output
4
思路:先正着遍历一遍,再反着遍历一遍,碰到积分与奖品多少不对等的情况,一直向上加一,直到积分与奖品的多少对等为止。

#include<stdio.h>
int main()
{
	int n,i,a[100000],b[100000];
	long long sum=0;//注意题目所给的范围很大,所以结果有可能会超过int范围。
	scanf("%d",&n);
	for(i=0;i<n;i++)
	{
		scanf("%d",&a[i]);
	}
	
	for(i=0;i<n;i++)
	{
		if(a[i]>a[i-1])
		{
			b[i]=b[i-1]+1;
		}
		else
		{
			b[i]=1;
		}
	}
	for(i=n-1;i>=1;i--)
	{
		if(a[i]>=a[i-1])
		continue;
	    else
     	{
		if(b[i-1]<=b[i])
		{
			b[i-1]=b[i]+1;
		}
		
     	}
    }
	for(i=0;i<n;i++)
	{
		sum=sum+b[i];
	}
	printf("%lld",sum);
}

关于vjudge

出现超时检查一下数组是否足够大;
如果答案部分正确检查以下结果是否溢出;
选对语言。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值