#牛客网 牛客假日团队赛5

A-Bad Hair Day 

 

题目描述

Some of Farmer John's N cows (1 ≤ N ≤ 80,000) are having a bad hair day! Since each cow is self-conscious about her messy hairstyle, FJ wants to count the number of other cows that can see the top of other cows' heads.
Each cow i has a specified height hi (1 ≤ hi ≤ 1,000,000,000) and is standing in a line of cows all facing east (to the right in our diagrams). Therefore, cow i can see the tops of the heads of cows in front of her (namely cows i+1, i+2, and so on), for as long as these cows are strictly shorter than cow i.

Consider this example:

=
= =
= - = Cows facing right -->
= = =
= - = = =

= = = = = =

1 2 3 4 5 6 Cow#1 can see the hairstyle of cows #2, 3, 4
Cow#2 can see no cow's hairstyle
Cow#3 can see the hairstyle of cow #4
Cow#4 can see no cow's hairstyle
Cow#5 can see the hairstyle of cow 6
Cow#6 can see no cows at all!
Let ci denote the number of cows whose hairstyle is visible from cow i; please compute the sum of c1 through cN.For this example, the desired is answer 3 + 0 + 1 + 0 + 1 + 0 = 5.

输入描述:

Line 1: The number of cows, N.
Lines 2..N+1: Line i+1 contains a single integer that is the height of cow i.

输出描述:

Line 1: A single integer that is the sum of c1 through cN.

示例1

输入

 

6
10
3
7
4
12
2

输出

 

5

题目大意 : 每头牛面朝一个方向,各自有各自的高度,每头牛只能看到比自己矮的牛,输出所有牛可以看到的牛的数量

思路 : 用栈遍历,如果下一头牛的高度比栈顶的牛要矮,那么把它加进去,否则,直到出现比将要进栈的牛高的牛时,再把这头牛给加进去,并更新此时栈内剩下的牛可以看到的牛的数量,注意存的是下标,这样就可以将两头牛之间的距离表示出来了

AC代码 :

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 5;
const int INF = 0x3f3f3f3f;

ll p[MAXN], n, ans;
stack <ll> st;

int main()
{
    cin >> n;
    for (int i = 0; i < n; i++) cin >> p[i];
    p[n] = INF;  // 将所有牛都弹出
    for (int i = 0; i <= n; i++) {
        if (st.empty() || p[st.top()] > p[i]) st.push(i);
        else {
            while (!st.empty() && p[i] >= p[st.top()]) {
                ll temp = st.top();
                st.pop();
                ans += i - temp - 1;  // 更新剩下的那头牛可以看到的牛的数量
            }
            st.push(i);
        }
    }
    cout << ans << endl;
    return 0;
}

B-切长条 


 

题目描述

给定如图所示的若干个长条。你可以在某一行的任意两个数之间作一条竖线,从而把这个长条切开,并可能切开其他长条。问至少要切几刀才能把每一根长条都切开。样例如图需要切两刀。

注意:输入文件每行的第一个数表示开始的位置,而第二个数表示长度。

输入描述:

Line 1: A single integer, N(2 <= N <= 32000)
Lines 2..N+1: Each line contains two space-separated positive integers that describe a leash. The first is the location of the leash's stake; the second is the length of the leash.(1 <= length <= 1e7)

输出描述:

Line 1: A single integer that is the minimum number of cuts so that each leash is cut at least once.

示例1

输入

 

7
2 4
4 7
3 3
5 3
9 4
1 5
7 3

输出

 

2

 

 题目大意: 输入一个区间,输出最少需要几刀才可以将每个区间都切开

思路 : 先排序,将尾部靠前的放前边,其次将首部靠前的放前边,从第一个开始遍历,如果遇到该点的尾小于下一个点的头,那么 刀数 + 1, 注意输入的是首部位置和长度 (以为是首尾位置WA了好几发)

AC代码 :

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;

struct node
{
    int x, y;
}p[MAXN];
bool cmp (node a, node b) {
    if (a.y == b.y) return a.x < b.x;
    else return a.y < b.y;
}
int n, ans, ui, vi;

int main()
{
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> ui >> vi;
        p[i].x = ui;
        p[i].y = ui + vi - 1;   // 记录尾部
    }
    sort (p, p + n, cmp);
    for (int i = 0; i < n - 1; i++) {
        bool flag = 1;
        for (int j = i + 1; j < n; j++) {
            if (p[i].y < p[j].x) {flag = 0, ans++, i = j - 1; break;}  //更新下一个
        }
        if (flag) break;
    }
    cout << ans + 1 << endl;
    return 0;
}

 C-Cows Of The Round Table 


 

题目描述

Farmer John is calling his N (1 <= N <= 10) cows to a very important meeting at a round table.
The cows are rather anxious about this meeting since they want to put forth their very best image. To make the table arrangement attractive, they want to ensure that any two cows sitting next to each other to differ in height by no more than K (1 <= K <= 1,000,000) millimeters (cow i has integer height Hi (1 <= Hi <= 1,000,000) millimeters).
Help calculate the number of ways the cows can sit down at the round table such that no two adjacent cows differ in height by more than K millimeters. Two ways are different if there is at least one cow with a different cow to its left in each arrangement.
The answer is guaranteed to fit in a 32-bit signed integer.

输入描述:

Line 1: Two space-separated integers, N and K
Lines 2..N+1: Line i+1 contains height Hi

输出描述:

Line 1: The number of ways that the cows can sit down at the round table such that two adjacent cows do not differ in height by more than K millimeters.

示例1

输入

 

4 10
2
16
6
10

输出

 

2

说明

There are 4 cows, with heights 2, 16, 6, and 10. Two cows whose heights differ by more than 10 do not want to sit next to each other.
Clearly the cows with heights 2 and 16 must be opposite each other, so there are 2 ways to place the cows of height 6 and 10.

题目大意 : 输入牛的数量和限制高度,输出有多少种坐法(所有牛围成一圈)可以让相邻两头牛的高度不超过K

思路 : 由于数据比较小,可以全排列所有的情况,然后依次判断即可,注意全排列排的是下标

AC代码 :

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 10 + 5;

int p[MAXN], s[MAXN], n, k, ans;

int main()
{
    cin >> n >> k;
    for (int i = 1; i <= n; i++) cin >> p[i];
    sort (p + 1, p + n + 1);   // 先排序
    for (int i = 1; i <= n; i++) s[i] = i;
    do {
        bool flag = 1;
        if (abs (p[s[1]] - p[s[n]]) > k) flag = 0;  // 首尾判断
        else {
            for (int i = 2; i <= n; i++) {
                if (abs (p[s[i]] - p[s[i - 1]]) > k) {
                    flag = 0;
                    break;
                }
            }
        }
        if (flag) ans++;
    }
    while (next_permutation (s + 1, s + n + 1));
    cout << ans / n << endl;   // 每种情况都有n - 1个重复的,所以要除以n
    return 0;
}

D-饥饿的牛

 思路 : 最长上升序列模板题

AC代码 :

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 5e3 + 5;

int p[MAXN], ans[MAXN], n, X = 1;

int main()
{
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> p[i];
    ans[1] = p[1];
    for (int i = 2; i <= n; i++) {
        if (p[i] > ans[X]) ans[++X] = p[i];
        else {
            int j = lower_bound(ans + 1, ans + X + 1, p[i]) - ans;
            ans[j] = p[i];
        }
    }
    cout << X << endl;
    return 0;
}

E-The Eating Puzzle 

 

题目描述

Bessie is on a diet where she can eat no more than C (10 ≤ C ≤ 35,000) calories per day. Farmer John is teasing her by putting out B (1 ≤ B ≤ 21) buckets of feed, each with some (potentially non-unique) number of calories (range: 1..35,000). Bessie has no self-control: once she starts on a feed bucket, she consumes all of it.
Bessie is not so good at combinatorics. Determine the optimal combination of feed buckets that gives Bessie as many calories without exceeding the limit C.
As an example, consider a limit of 40 calories and 6 buckets with 7, 13, 17, 19, 29, and 31 calories. Bessie could eat 7 + 31 = 38 calories but could eat even more by consuming three buckets: 7 + 13 + 19 = 39 calories. She can find no better combination.

输入描述:

Line 1: Two space-separated integers: C and B
Line 2: B space-separated integers that respectively name the number of calories in bucket 1, 2, etc.

输出描述:

Line 1: A single line with a single integer that is largest number of calories Bessie can consume and still stay on her diet.

示例1

输入

 

40 6
7 13 17 19 29 31

输出

 

39

 题目大意 : 输入N个数字和一个上限,求出若干个数的和的最大值 (不超过上限)

思路 : 数据比较大,不能用DFS,直接用背包做就好

AC代码 :

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;

int p[MAXN], dp[MAXN], n, m;

int main()
{
    cin >> m >> n;
    for (int i = 1; i <= n; i++) cin >> p[i];
    for (int i = 1; i <= n; i++) {
        for (int j = m; j >= p[i]; j--)
            dp[j] = max (dp[j], dp[j - p[i]] + p[i]);
    }
    cout << dp[m] << endl;
    return 0;
}

 

 H-数字游戏

 

奶牛们又在玩一种无聊的数字游戏。输得很郁闷的贝茜想请你写个程序来帮她在开局时预测结果。在游戏的开始,每头牛都会得到一个数N(1<=N<=1,000,000)。此时奶牛们的分数均为0。如果N是奇数,那么奶牛就会把它乘以3后再加1。如果N是偶数,那么这个数就会被除以2。数字每变动一次,这头奶牛就得到1分。当N的值等于1时,游戏结束,此时的分数就是这头奶牛在这局游戏中的最终得分。
以下是N=5时,一局游戏的完整过程:

N   操作后所得数 注释   总分
5        16          3*5+1       1
16         8           16/2       2
8         4            8/2       3
4         2            4/2       4
2         1            2/2       5

输入描述:

第1行: 一个正整数,N

输出描述:

第1行: 输出一个正整数N,即奶牛在这局游戏中的最终得分

示例1

输入

 

112

输出

 

20

思路 : 直接模拟就好

AC代码 :

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;

int main()
{
    ll n, ans = 0;
    cin >> n;
    while (n != 1) {
        if (n & 1) n = n * 3 + 1;
        else n /= 2;
        ans++;
    }
    cout << ans << endl;
    return 0;
}

I-Protecting the Flowers  


 

题目描述

Farmer John went to cut some wood and left N (2 ≤ N ≤ 100,000) cows eating the grass, as usual. When he returned, he found to his horror that the cluster of cows was in his garden eating his beautiful flowers. Wanting to minimize the subsequent damage, FJ decided to take immediate action and transport each cow back to its own barn.
Each cow i is at a location that is Ti minutes (1 ≤ Ti ≤ 2,000,000) away from its own barn. Furthermore, while waiting for transport, she destroys Di (1 ≤ Di ≤ 100) flowers per minute. No matter how hard he tries, FJ can only transport one cow at a time back to her barn. Moving cow i to its barn requires 2 × Ti minutes (Ti to get there and Ti to return). FJ starts at the flower patch, transports the cow to its barn, and then walks back to the flowers, taking no extra time to get to the next cow that needs transport.
Write a program to determine the order in which FJ should pick up the cows so that the total number of flowers destroyed is minimized.

输入描述:

Line 1: A single integer N
Lines 2..N+1: Each line contains two space-separated integers, Ti and Di, that describe a single cow's characteristics

输出描述:

Line 1: A single integer that is the minimum number of destroyed flowers

示例1

输入

 

6
3 1
2 5
2 3
3 2
4 1
1 6

输出

 

86

 题目大意 : 每行两个数分别表示这头牛每分钟会摧毁的花的数量和送走需要的时间,求出最少会被摧毁的花的数量

思路 : 性价比问题,按每分钟摧毁的数量的大小进行排序即可

AC代码 :

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 5;

struct node
{
    double time, val, id;
}p[MAXN];
bool cmp (node a, node b) {
    return a.id > b.id;
}
int n;
double sum;
ll ans;
int main()
{
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> p[i].time >> p[i].val;
        p[i].time *= 2;
        p[i].id = p[i].val / p[i].time;
        sum += p[i].val;
    }
    sort (p, p + n, cmp);
    for (int i = 0; i < n; i++) {
        sum -= p[i].val;
        ans += sum * p[i].time;
    }
    cout << ans << endl;
    return 0;
}

J-护城河 

 

题目描述

为了防止口渴的食蚁兽进入他的农场,Farmer John决定在他的农场周围挖一条护城河。农场里一共有N(8<=N<=5,000)股泉水,并且,护城河总是笔直地连接在河道上的相邻的两股泉水。护城河必须能保护所有的泉水,也就是说,能包围所有的泉水。泉水一定在护城河的内部,或者恰好在河道上。当然,护城河构成一个封闭的环。
挖护城河是一项昂贵的工程,于是,节约的FJ希望护城河的总长度尽量小。请你写个程序计算一下,在满足需求的条件下,护城河的总长最小是多少。
所有泉水的坐标都在范围为(1..10,000,000,1..10,000,000)的整点上,一股泉水对应着一个唯一确定的坐标。并且,任意三股泉水都不在一条直线上。
以下是一幅包含20股泉水的地图,泉水用"*"表示:

...*-----------------*......
../..........*........\.....
./.....................\....
*......................*\...
|..........*........*....\..
|*........................\.
|..........................*
*..........................|
.\*........................|
..\.....................*..|
...\........*............*.|
....\..................*...*
.....\..*..........*....../.
......\................../..
.......*----------------*...
(请复制到记事本中用等宽字体查看)

图中的直线,为护城河的最优挖掘方案,即能围住所有泉水的最短路线。
路线从左上角起,经过泉水的坐标依次是:(18,0),(6,-6),(0,-5),(-3,-3),(-17,0),(-7,7),(0,4),(3,3)。绕行一周的路径总长为70.8700576850888(...)。答案只需要保留两位小数,于是输出是70.87。

输入描述:

第1行: 一个整数,N
第2..N+1行: 每行包含2个用空格隔开的整数,x[i]和y[i],即第i股泉水的位置坐标

输出描述:

第1行: 输出一个数字,表示满足条件的护城河的最短长度。保留两位小数

示例1

输入

 

20
2 10
3 7
22 15
12 11
20 3
28 9
1 12
9 3
14 14
25 6
8 1
25 1
28 4
24 12
4 15
13 5
26 5
21 11
24 4
1 8

输出

 

70.87

题目大意  : 有N个泉水,只能在各个泉水之间连线,输出最少的路程可以将所有泉水围住

思路 :先对坐标进行排序,找到最下面的点,如果有多个选取任意一个都行,然后把第一个点存到栈中,对其他点按照极角大小进行排序 (极角相同则距离第一个点近的靠前),将排序后的第一个点存入栈,再依次遍历其他点,如果栈顶的两个元素A, B,与该点C满足 :向量AC 在向量BC的左边,那么就将C加入栈,否则,弹出栈顶元素,再用栈顶前两个元素与该点进行判断,最后输入每个点之间的距离即可

AC代码 :

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e4 + 5;

struct node
{
	int x, y;
}p[MAXN], st[MAXN];
int n, xx, yy;
bool cmp1(node a, node b) {  // 第一次排序,找到最下面的初始点
	if (a.y == b.y) return a.x < b.x;
	else return a.y < b.y;
}
int cross(node a, node b, node c) {  // 叉积
	return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y);
}
double dis(node a, node b) { // 每个点之间距离
	return sqrt((a.x - b.x) * (a.x - b.x) * 1.0 + (a.y - b.y) * (a.y - b.y));
}
bool cmp(node a, node b) {  // 第二次对极角进行排序,极角相同按距离从小到大排
	int m = cross(p[0], a, b);
	if (m > 0) return 1;
	else if (!m && dis(p[0], a) - dis(p[0], b) <= 0) return 1;
	else return 0;
}

int main()
{
	cin >> n;
	for (int i = 0; i < n; i++) cin >> p[i].x >> p[i].y;
	if (n == 1) printf("%.2f\n", 0.00);
	else if (n == 2) printf("%.2f\n", dis(p[0], p[1]));
	else {
		sort(p, p + n, cmp1);
		st[0] = p[0];  // 保存起始点
		xx = st[0].x, yy = st[0].y;
		sort(p + 1, p + n, cmp);
		st[1] = p[1];  // 保存第二个点
		int top = 1;  
		for (int i = 2; i < n; i++) {  
			while (i >= 1 && cross(st[top - 1], st[top], p[i]) < 0)
				top--;
			st[++top] = p[i];
		}
		double s = 0;
		for (int i = 1; i <= top; i++)
			s += dis(st[i - 1], st[i]);
		s += dis(st[top], p[0]);
		printf("%.2f\n", s);
	}
	return 0;
}

K-金币馅饼 

 

题目描述

最近,奶牛们热衷于把金币包在面粉里,然后把它们烤成馅饼。第i块馅饼中含有Ni(1<=Ni<=25)块金币,并且,这个数字被醒目地标记在馅饼表面。
奶牛们把所有烤好的馅饼在草地上排成了一个R行(1<=R<=100)C列(1<=C<=100)的矩阵。你现在站在坐标为(1,1)的馅饼边上,当然,你可以拿到那块馅饼里的所有金币。你必须从现在的位置,走到草地的另一边,在坐标为(R,C)的馅饼旁边停止走动。每做一次移动,你必须走到下一列的某块馅饼旁边,并且,行数的变动不能超过1(也就是说,如果现在你站在坐标为(r,c)的馅饼边上,下一步你可以走到坐标为(r-1,c+1),(r,c+1),或者(r+1,c+1)的馅饼旁边)。当你从一块馅饼边经过,你就可以拿走馅饼里所有的金币。当然啦,你一定不会愿意因半路离开草地而失去唾手可得的金币,但,最终你一定得停在坐标为(R,C)的馅饼旁边。

现在,你拿到了一张标记着馅饼矩阵中,每一块馅饼含金币数量的表格。那么,按照规则,你最多可以拿到多少金币呢?

比方说,奶牛们把馅饼排成如下的矩阵,矩阵中的数字表示该位置的馅饼中含金币的数量:

起点-> 6 5 3 7 9 2 7
    2 4 3 5 6 8 6
    4 9 9 9 1 5 8 <-终点
以下是一条合法的路线:

起点-> 6 5 3 7 9 2 7
     \
    2 4 3 5 6 8 6
       \   / \
    4 9 9-9 1 5-8 <-终点
按上述的路线进行走动,一共可以获得6+4+9+9+6+5+8=47个金币。按照规则,在这个矩阵中最多可以得到50个金币,路线如下图所示:

起点-> 6 5 3 7 9 2 7
     \
    2 4 3 5 6-8 6
       \   /   \
    4 9 9-9 1 5 8 <-终点

(请复制到记事本中用等宽字体查看)

 

输入描述:

第1行: 两个用空格隔开的整数,R和C
第2..R+1行: 每行包含C个用空格隔开的正整数,依次表示一行中从左往右各个馅饼里金币的数量

输出描述:

第1行: 输出一个正整数,表示你所能收集到的最大金币数目

示例1

输入

 

3 7
6 5 3 7 9 2 7
2 4 3 5 6 8 6
4 9 9 9 1 5 8

输出

 

50

题目大意 : 只能向右上、右、右下走,每次将该点的馅饼捡起,输出从(1, 1) 到 (m, n)可以得到的馅饼的最大数目

思路 : 用dp写,画画图就会了

AC代码 :

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e2 + 5;

int p[MAXN][MAXN], dp[MAXN][MAXN], n, m;

int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) cin >> p[i][j];
    }
    for (int i = 1; i <= n; i++) dp[i][i] = dp[i - 1][i - 1] + p[i][i];
    for (int i = 2; i <= m; i++) {
        for (int j = 1; j <= i; j++)
            dp[j][i] = max(max(dp[j + 1][i - 1], dp[j][i - 1]), dp[j - 1][i - 1]) + p[j][i];
    }
    cout << dp[n][m] << endl;
    return 0;
}

L-Catch That Cow


 

题目描述

Farmer John has been informed of the location of a fugitive cow and wants to catch her immediately. He starts at a point N (0 <= N <= 100,000) on a number line and the cow is at a point K (0 <= K <= 100,000) on the same number line. Farmer John has two modes of transportation: walking and teleporting.
Walking: FJ can move from any point X to the points X-1 or X+1 in a single minute Teleporting: FJ can move from any point X to the point 2*X in a single minute.
If the cow, unaware of its pursuit, does not move at all, how long does it take for Farmer John to retrieve it?

输入描述:

Line 1: Two space-separated integers: N and K

输出描述:

Line 1: The least amount of time, in minutes, it takes for Farmer John to catch the fugitive cow.

示例1

输入

 

5 17

输出

 

4

说明

Farmer John starts at point 5 and the fugitive cow is at point 17.
The fastest way for Farmer John to reach the fugitive cow is to move along the following path: 5-10-9-18-17, which takes 4 minutes.

 

 

题目大意 :  每次有三种选择 : +1, -1,  * 2. 输出从起点到终点 的最短路程

思路 : bfs裸题

AC代码 :

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int MAXN = 1e5 + 5;

struct node
{
    ll x, step;
};
ll n, k;
bool vis[MAXN];
void bfs() {
    queue <node> q;
    q.push({n, 0});
    vis[n] = 1;
    while (!q.empty()) {
        node now = q.front();
        q.pop();
        if (now.x == k) {
            cout << now.step << endl;
            return;
        }
        ll xx;
        for (int i = 0; i < 3; i++) {
            if (i == 0) xx = now.x + 1;
            else if (i == 2) xx = now.x - 1;
            else xx = now.x * 2;
            if (xx >= 0 && xx <= 100000 && !vis[xx]) {
                vis[xx] = 1;
                q.push({xx, now.step + 1});
            }
        }
    }
}

int main()
{
    cin >> n >> k;
    bfs();
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值