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

A-Card Stacking

题目描述

Bessie is playing a card game with her N-1 (2 <= N <= 100) cow friends using a deck with K (N <= K <= 100,000; K is a multiple of N) cards.  The deck contains M = K/N "good" cards and K-M "bad" cards. Bessie is the dealer and, naturally, wants to deal herself all of the "good" cards. She loves winning.
Her friends suspect that she will cheat, though, so they devise a dealing system in an attempt to prevent Bessie from cheating. They tell her to deal as follows:
   1. Start by dealing the card on the top of the deck to the cow to her right
   2. Every time she deals a card, she must place the next P (1 <= P <= 10) cards on the bottom of the deck; and
   3. Continue dealing in this manner to each player sequentially in a counterclockwise manner
Bessie, desperate to win, asks you to help her figure out where she should put the "good" cards so that she gets all of them. Notationally, the top card is card #1, next card is #2, and so on.

输入描述:

* Line 1: Three space-separated integers: N, K, and P

输出描述:

* Lines 1..M: Positions from top in ascending order in which Bessie should place "good" cards, such that when dealt, Bessie will obtain all good cards.

示例1

输入

 

3 9 2

输出

 

3
7
8

说明

Bessie should put the "good" cards in positions 3, 7, and 8. The cards will be dealt as follows; the card numbers are "position in original deck":
Card Deck         P1      P2    Bessie
Initial configuration           1 2 3 4 5 6 7 8 9  - - -   - - -   - - -
Deal top card [1] to Player 1   2 3 4 5 6 7 8 9    1 - -   - - -   - - -
Top card to bottom (#1 of 2)    3 4 5 6 7 8 9 2    1 - -   - - -   - - -
Top card to bottom (#2 of 2)    4 5 6 7 8 9 2 3    1 - -   - - -   - - -
Deal top card [4] to Player 2   5 6 7 8 9 2 3      1 - -   4 - -   - - -
Top card to bottom (#1 of 2)    6 7 8 9 2 3 5      1 - -   4 - -   - - -
Top card to bottom (#2 of 2)    7 8 9 2 3 5 6      1 - -   4 - -   - - -
Deal top card [7] to Bessie     8 9 2 3 5 6        1 - -   4 - -   7 - -
Top card to bottom (#1 of 2)    9 2 3 5 6 8        1 - -   4 - -   7 - -
Top card to bottom (#2 of 2)    2 3 5 6 8 9        1 - -   4 - -   7 - -
Deal top card [2] to Player 1   3 5 6 8 9          1 2 -   4 - -   7 - -
Top card to bottom (#1 of 2)    5 6 8 9 3          1 2 -   4 - -   7 - -
Top card to bottom (#2 of 2)    6 8 9 3 5          1 2 -   4 - -   7 - -
Deal top card [6] to Player 2   8 9 3 5            1 2 -   4 6 -   7 - -
Top card to bottom (#1 of 2)    9 3 5 8            1 2 -   4 6 -   7 - -
Top card to bottom (#2 of 2)    3 5 8 9            1 2 -   4 6 -   7 - -
Deal top card [3] to Bessie     5 8 9              1 2 -   4 6 -   7 3 -
Top card to bottom (#1 of 2)    8 9 5              1 2 -   4 6 -   7 3 -
Top card to bottom (#2 of 2)    9 5 8              1 2 -   4 6 -   7 3 -
Deal top card [9] to Player 1   5 8                1 2 9   4 6 -   7 3 -
Top card to bottom (#1 of 2)    8 5                1 2 9   4 6 -   7 3 -
Top card to bottom (#2 of 2)    5 8                1 2 9   4 6 -   7 3 -
Deal top card [5] to Player 2   8                  1 2 9   4 6 5   7 3 -
Top card to bottom (#1 of 2)    8                  1 2 9   4 6 5   7 3 -
Top card to bottom (#1 of 2)    8                  1 2 9   4 6 5   7 3 -
Deal top card [8] to Bessie     -                  1 2 9   4 6 5   7 3 8
Bessie will end up with the "good cards" that have been placed in positions 3, 7, and 8 in the original deck.

题目大意 :N个人, M张牌, (M一定能整除N), 每发一张牌就将牌顶的P张牌放到牌堆底部,从小到大输出最后一个人获得的牌 

思路 : 直接模拟就好

AC代码 :

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

queue <int> q;
set <int> st;
int n, k, p, cnt, ans = 1, temp;

int main()
{
	cin >> n >> k >> p;
	cnt = k / n;  // 每个人cnt张牌
	for (int i = 1; i <= k; i++) q.push(i); //入队
	while (!q.empty()) {  
		if (st.size() == cnt) break;  
		for (int i = 1; i < n; i++) {  // 发牌给前面的人并洗牌
			q.pop();  // 发牌,不需要记录
			for (int j = 0; j < p; j++) {  // 洗牌
				temp = q.front();
				q.pop();
				q.push(temp);
			}
		}
		st.insert(q.front());  // 加入
		q.pop();
		if (q.size()) {
			for (int j = 0; j < p; j++) {  // 洗牌
				temp = q.front();
				q.pop();
				q.push(temp);
			}
		}
	}
	for (auto it : st) cout << it << endl;
	return 0;
}

B-Bookshelf

64bit IO Format: %lld

题目描述

Farmer John recently bought a bookshelf for cow library, but the shelf is getting filled up quite quickly, and now the only available space is at the top.
Each of the N cows (1 <= N <= 20,000) has some height of Hi (1 <= Hi <= 10,000) and a total height summed across all N cows of S. The bookshelf has a height of B (1 <= B <= S < 2,000,000,007).
To reach the top of the bookshelf taller than the tallest cow, one or more of the cows can stand on top of each other in a stack, so that their total height is the sum of each of their individual heights. This total height must be no less than the height of the bookshelf. Since more cows than necessary in the stack can be dangerous, your job is to find the set of cows that produces a stack of the smallest number of cows possible such that the stack can

输入描述:

* Line 1: Two space-separated integers: N and B
* Lines 2..N+1: Line i+1 contains a single integer: Hi

输出描述:

* Line 1: A single integer representing the size of the smallest set of cows that can reach the bookshelf.

示例1

输入

 

6 40
6
18
11
13
19
11

输出

 

3

说明

Six cows; bookshelf height 40. Cow heights fall in the range 6..19.
One way to reach 40 with 3 cows is 18+11+13; many others exist

 题目大意 : 输入N个数, 输出和小于等于M的数的最大值

思路 :排序模拟

AC代码 :

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

ll p[MAXN], n, k, ans, sum;

int main()
{
	cin >> n >> k;
	for (ll i = 0; i < n; i++) cin >> p[i];
	sort(p, p + n);
	for (ll i = n - 1; i >= 0; i--) {
		ans += p[i], sum++;
		if (ans >= k) break;
	}
	cout << sum << endl;
	return 0;
}

C-Bookshelf 2

题目描述

Farmer John recently bought another bookshelf for the cow library, but the shelf is getting filled up quite quickly, and now the only available space is at the top.
FJ has N cows (1 <= N <= 20) each with some height of Hi (1 <= Hi <= 1,000,000 - these are very tall cows). The bookshelf has a height of B (1 <= B <= S, where S is the sum of the heights of all cows).
To reach the top of the bookshelf, one or more of the cows can stand on top of each other in a stack, so that their total height is the sum of each of their individual heights. This total height must be no less than the height of the bookshelf in order for the cows to reach the top.
Since a taller stack of cows than necessary can be dangerous, your job is to find the set of cows that produces a stack of the smallest height possible such that the stack can reach the bookshelf. Your program should print the minimal 'excess' height between the optimal stack of cows and the bookshelf.

输入描述:

* Line 1: Two space-separated integers: N and B
* Lines 2..N+1: Line i+1 contains a single integer: Hi

输出描述:

* Line 1: A single integer representing the (non-negative) difference between the total height of the optimal set of cows and the height of the shelf.

示例1

输入

 

5 16
3
1
3
5
6

输出

 

1

说明

Here we use cows 1, 3, 4, and 5, for a total height of 3 + 3 + 5 + 6 = 17.
It is not possible to obtain a total height of 16, so the answer is 1.

 题目大意 : 输入N个数, 选取其中部分数, 和大于M并使二者差值最小

思路 : 01背包问题

AC代码 :

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

ll p[MAXN], dp[MAXN], n, k, V;

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

D-迷路的牛

题目描述

Farmer John的三头获奖奶牛Bessie、Elsie和Mildred,总是会迷路走到农场上遥远的地方去!他需要你帮助将她们一起赶回来。

农场的草地大体是一块狭长的区域——我们可以将其想象成一条数轴,奶牛可以占据数轴上的任意整数位置。这3头奶牛现在正位于不同的整数位置,Farmer John想要移动她们,使得她们占据三个相邻的位置(例如,位置6、7、8)。

不幸的是,奶牛们现在很困,Farmer John要让她们集中精力听从命令移动并不容易。任意时刻,他只能使得一头处在“端点”(在所有奶牛中位置最小或最大)位置的奶牛移动。当他移动奶牛时,他可以命令她走到任意一个未被占用的整数位置,只要在新的位置上她不再是一个端点。可以看到随着时间的推移,这样的移动可以使奶牛们趋向越来越近。

请求出使得奶牛们集中到相邻位置所进行的移动次数的最小和最大可能值。

输入描述:

输入包含一行,包括三个空格分隔的整数,为Bessie、Elsie和Mildred的位置。每个位置均为一个范围1…10^9内的整数。

输出描述:

输出的第一行包含Farmer John需要将奶牛们聚集起来所需进行的最小移动次数。第二行包含他将奶牛聚集起来能够进行的最大移动次数。

示例1

输入

 

4 7 9

输出

 

1
2

说明

最小移动次数为1——如果Farmer John将位置4的奶牛移动到位置8,那么奶牛们就处在连续的位置7、8、9。最大移动次数为2。例如,位置9的奶牛可以被移动到位置6,然后位置7的奶牛可以被移动到位置5。

备注:

 

输入的数在[1,10^9]范围内

题目大意 : 输入三个数分别表示三个数所在的位置,输出最小和最大的操作次数,使三者满足a + 1 == b, b + 1 == c, 每次只能让两边的数放入中间

思路 :  最小操作次数只有三种情况,0, 1, 2。 要么已经分好, 要么差一步分好, 要么差的很远(差的远也可以将最外边的数移到我们想要的地方), 剩下最大的情况就是两个数交替向中间靠拢

AC代码 :

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

ll ai, bi, ci;

int main()
{
	cin >> ai >> bi >> ci;
	if (ai + 1 == bi && ai + 2 == ci) cout << 0 << endl;
	else if (ai + 2 == bi || bi + 2 == ci) cout << 1 <<endl;
	else cout << 2 << endl;
	cout << max(bi - ai, ci - bi) - 1 << endl;
	return 0;
}

E-对牛排序

题目描述

Farmer John正在尝试将他的N头奶牛(1≤N≤100),方便起见编号为1…N,在她们前往牧草地吃早餐之前排好顺序。

当前,这些奶牛以p1,p2,p3,…,pN的顺序排成一行,Farmer John站在奶牛p1前面。他想要重新排列这些奶牛,使得她们的顺序变为1,2,3,…,N奶牛1在Farmer John旁边。

今天奶牛们有些困倦,所以任何时刻都只有直接面向Farmer John的奶牛会注意听Farmer John的指令。每一次他可以命令这头奶牛沿着队伍向后移动k步,k可以是范围1…N−1中的任意数。她经过的k头奶牛会向前移动,腾出空间使得她能够插入到队伍中这些奶牛之后的位置。

例如,假设N=4,奶牛们开始时是这样的顺序:

 FJ: 4, 3, 2, 1 

唯一注意FJ指令的奶牛是奶牛4。当他命令她向队伍后移动2步之后,队伍的顺序会变成:

 FJ: 3, 2, 4, 1 

现在唯一注意FJ指令的奶牛是奶牛3,所以第二次他可以给奶牛3下命令,如此进行直到奶牛们排好了顺序。

Farmer John急欲完成排序,这样他就可以回到他的农舍里享用他自己的早餐了。请帮助他求出将奶牛们排好顺序所需要的最小操作次数。

输入描述:

输入的第一行包含N。

第二行包含N个空格分隔的整数,p1,p2,p3,…,pN,表示奶牛们的起始顺序。

输出描述:

输出一个整数,为Farmer John采用最佳策略可以将这N头奶牛排好顺序所需要的操作次数。

示例1

输入

 

4
1 2 4 3

输出

 

3

备注:

1≤N≤100 pi≤N

 题目大意 : 需要将N头牛按递增排序, 一个人站在左边,所有牛面朝他, 每次只能将排头的牛移动任意步,输出最小需要多少次移动才可以排好序

思路 : 每个数从左往右, 找第一个比他小的数,记录下标,输出最后的下标(因为当你找到这样的数时,前面已经排好队了)

AC代码 :

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

int p[MAXN], n, ans;

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

F-Mud Puddles

题目描述

Farmer John is leaving his house promptly at 6 AM for his daily milking of Bessie. However, the previous evening saw a heavy rain, and the fields are quite muddy. FJ starts at the point (0, 0) in the coordinate plane and heads toward Bessie who is located at (X, Y) (-500 ≤ X ≤ 500; -500 ≤ Y ≤ 500). He can see all N (1 ≤ N ≤ 10,000) puddles of mud, located at points (Ai, Bi) (-500 ≤ Ai ≤ 500; -500 ≤ Bi ≤ 500) on the field. Each puddle occupies only the point it is on.
Having just bought new boots, Farmer John absolutely does not want to dirty them by stepping in a puddle, but he also wants to get to Bessie as quickly as possible. He's already late because he had to count all the puddles. If Farmer John can only travel parallel to the axes and turn at points with integer coordinates, what is the shortest distance he must travel to reach Bessie and keep his boots clean? There will always be a path without mud that Farmer John can take to reach Bessie.

输入描述:

* Line 1: Three space-separate integers: X, Y, and N.
* Lines 2..N+1: Line i+1 contains two space-separated integers: Ai and Bi

输出描述:

* Line 1: The minimum distance that Farmer John has to travel to reach Bessie without stepping in mud.

示例1

输入

 

1 2 7
0 2
-1 3
3 1
1 1
4 2
-1 1
2 2

输出

 

11

说明

Bessie is at (1, 2). Farmer John sees 7 mud puddles, located at (0, 2); (-1, 3); (3, 1); (1, 1); (4, 2); (-1, 1) and (2, 2).
The best path for Farmer John is (0, 0); (-1, 0); (-2, 0); (-2, 1); (-2, 2); (-2, 3); (-2, 4); (-1, 4); (0, 4); (0, 3); (1, 3); and (1, 2), finally reaching Bessie.

题目大意 : 输入坐标轴上的若干个点,表示该点不可走, 每次只能朝上下左右 四个方向走, 输出起点到终点的最短路

思路 : 将每个数的左边 + 505, 就可以用数组存了, 然后直接裸的BFS,注意边界处要扩大一圈

AC代码 :

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

struct node
{
	int x, y, step;
};
int ex, ey, ab = -INF, be = INF, ri = -INF, le = INF, n;
int dir[4][2] = { 1, 0, -1, 0, 0, 1, 0, -1 };
bool vis[MAXN][MAXN], mp[MAXN][MAXN];
queue <node> q;
void bfs() {
	q.push({ 505, 505, 0 });
	while (!q.empty()) {
		node now = q.front();
		q.pop();
		if (now.x == ex && now.y == ey) {
			cout << now.step << endl;
			return;
		}
		for (int i = 0; i < 4; i++) {
			int xx = now.x + dir[i][0];
			int yy = now.y + dir[i][1];
			if (xx >= le && xx <= ri && yy >= be && yy <= ab && !vis[xx][yy] && !mp[xx][yy]) {
				vis[xx][yy] = 1;
				q.push({ xx, yy, now.step + 1 });
			}
		}
	}
}

int main()
{
	cin >> ex >> ey >> n;
	ex += 505, ey += 505;
	for (int i = 0; i < n; i++) {
		int ui, vi;
		scanf("%d%d", &ui, &vi);
		ui += 505, vi += 505;
		ab = max(ab, vi), ri = max(ri, ui);
		be = min(be, vi), le = min(le, ui);
		mp[ui][vi] = 1;
	}
	ab++, ri++, be--, le--;  // 边界扩大一圈
	bfs();
	return 0;
}

G-Cow Yahtzee

题目描述

奶牛们以它们一贯笨拙的方式玩Yahtzee,一种掷骰子的游戏。他们掷N次(1 <= N <= 20) S(1 <= S <= 8)面骰子。他们对于能满足一定标准的掷出骰子的结果的数量很感兴趣(类似“包含3个2”或者“包含一个2和两个3”)。
教他们学会概率。写一个程序,不仅读入N和S,而且还有一些说明这些标准的表达式。从骰子的所有可能的组合中找出符合表达式要求的组合的数量(3个2面骰子所有可能的组合是 {1,1,1; 1,1,2; 1,2,1; 1,2,2; 2,1,1; 2,1,2; 2,2,1; 2,2,2};)。
这种组合的最基本的形式表达了“希望至少有W份R”看上去像这样:
WxR
这里满足(0 <= W <= N and 1 <= R <= S)。每次检验运行提供E个表达式(1 <= E <= 20),每个包含1~10个由“+”分割的基本形式。“+”表示“且”(看下面)。行与行之间的关系是“或者”。这样,下面所示的表达式的意思是:“至少有三个5 或者 同时至少有1个3和至少2个4”:
3x5
1x3+2x4
这里有一些满足上述条件的4个5面骰可能的情况:5,5,5,1; 4,5,5,5; 3,4,4,2; 3,4,4,3;3,4,4,5; 4,4,5,3。
注意:确保你能从一行中读取2个整数并在下一行中能读取一个字符串。对有某些语言的I/O设计来说,这比看上去的更难。
同时注意所有骰子可能的组合数在提供的测试数据里不会超过1,512,768。

输入描述:

第 1 行: 三个由空格分开的整数: N, S 和 E
第 2 至 E+1 行: 第i+1 描述第i个表达式

输出描述:

第 1 行: 一个整数,从骰子的所有可能的组合中找出符合表达式要求的组合的数量

示例1

输入

 

4 5 2
3x5
1x3+2x4

输出

 

63

说明

这是按输入规则写的在上文中出现的情况。
63 种符合表达式的可能。

 

 题目大意 : 输入N行,行与行之间是或的关系, 每行里面是和的关系, 输出有多少种排列方式

思路: 直接暴力, 满足条件就 + 1, 用一个二维数组维护, 左表示行,右表示数字,值表示个数,这样就可以将或与和的关系体现出来了

AC代码 :

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

int a[MAXN][MAXN], b[MAXN], c[MAXN];
int n, m, k, ans;
string line;
void dfs(int x) {
	if (x == n + 1) {
		memset(c, 0, sizeof(c));
		for (int i = 1; i <= n; i++) c[b[i]]++;
		for (int i = 1; i <= k; i++) {
			bool flag = 1;
			for (int j = 1; j <= m; j++) {
				if (a[i][j] > c[j]) { flag = 0; break; }
			}
			if (flag) { ans++; return; }
		}
	}
	else {
		for (int i = 1; i <= m; i++) {
			b[x] = i;
			dfs(x + 1);
		}
	}
}

int main()
{
	cin >> n >> m >> k;
	for (int i = 1; i <= k; i++) {
		cin >> line;
		for (int j = 0; j < line.size(); j+= 4)
			a[i][line[j + 2] - '0'] = line[j] - '0';
	}
	dfs(1);
	cout << ans << endl;
	return 0;
}

H-Charm Bracelet

题目描述

Bessie has gone to the mall's jewelry store and spies a charm bracelet. Of course, she'd like to fill it with the best charms possible from the N (1 ≤ N ≤ 3,402) available charms. Each charm i in the supplied list has a weight Wi (1 ≤ Wi ≤ 400), a 'desirability' factor Di (1 ≤ Di ≤ 100), and can be used at most once. Bessie can only support a charm bracelet whose weight is no more than M (1 ≤ M ≤ 12,880).
Given that weight limit as a constraint and a list of the charms with their weights and desirability rating, deduce the maximum possible sum of ratings.

输入描述:

* Line 1: Two space-separated integers: N and M
* Lines 2..N+1: Line i+1 describes charm i with two space-separated integers: Wi and Di

输出描述:

* Line 1: A single integer that is the greatest sum of charm desirabilities that can be achieved given the weight constraints

示例1

输入

 

4 6
1 4
2 6
3 12
2 7

输出

 

23

 题目大意 : 01背包模板题

AC代码 :

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

int dp[MAXN], p[MAXN], val[MAXN], n, V;

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

J-Sightseeing Cows  

链接:https://ac.nowcoder.com/acm/contest/993/J
来源:牛客网
 

题目描述

Farmer John has decided to reward his cows for their hard work by taking them on a tour of the big city! The cows must decide how best to spend their free time.
Fortunately, they have a detailed city map showing the L (2 ≤ L ≤ 1000) major landmarks (conveniently numbered 1.. L) and the P (2 ≤ P ≤ 5000) unidirectional cow paths that join them. Farmer John will drive the cows to a starting landmark of their choice, from which they will walk along the cow paths to a series of other landmarks, ending back at their starting landmark where Farmer John will pick them up and take them back to the farm. Because space in the city is at a premium, the cow paths are very narrow and so travel along each cow path is only allowed in one fixed direction.
While the cows may spend as much time as they like in the city, they do tend to get bored easily. Visiting each new landmark is fun, but walking between them takes time. The cows know the exact fun values Fi (1 ≤ Fi ≤ 1000) for each landmark i.
The cows also know about the cowpaths. Cowpath i connects landmark L1iL1i to L2iL2i (in the direction L1iL1i -> L2iL2i ) and requires time Ti (1 ≤ Ti ≤ 1000) to traverse.
In order to have the best possible day off, the cows want to maximize the average fun value per unit time of their trip. Of course, the landmarks are only fun the first time they are visited; the cows may pass through the landmark more than once, but they do not perceive its fun value again. Furthermore, Farmer John is making the cows visit at least two landmarks, so that they get some exercise during their day off.
Help the cows find the maximum fun value per unit time that they can achieve.

输入描述:

* Line 1: Two space-separated integers: L and P
* Lines 2..L+1: Line i+1 contains a single one integer: Fi
* Lines L+2..L+P+1: Line L+i+1 describes cow path i with three space-separated integers: L1iL1i , L2iL2i , and Ti

输出描述:

* Line 1: A single number given to two decimal places (do not perform explicit rounding), the maximum possible average fun per unit time, or 0 if the cows cannot plan any trip at all in accordance with the above rules.

示例1

输入

 

5 7
30
10
10
5
10
1 2 3
2 3 2
3 4 5
3 5 2
4 5 5
5 1 3
5 2 2

输出

 

6.00

说明

The trip 1 -> 2 -> 3 -> 5 -> 1 has a total fun value of 60 and a length of 10 units for an average fun per unit time of 6. The trip 2 -> 3 -> 5 -> 2 only has an average fun per unit time of 30/6 = 5, and any trip involving landmark 4 has an average fun per unit time of less than 4.

题目大意 : 输入一个有向图, 每个点有权值, 每条边有权值, 存在环使得该环上点权值之和比上边权值之和最大, 输出该值

思路: spfa  +  01规划

AC代码 :

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

struct node
{
	int v, w, next;
	double wi;
}e[MAXN];
int head[MAXN], scnt[MAXN], val[MAXN], n, m, cnt;
double dis[MAXN]; 
bool vis[MAXN];
void add(int from, int to, int dis) {
	e[++cnt].v = to;
	e[cnt].w = dis;
	e[cnt].next = head[from];
	head[from] = cnt;
}
bool spfa(double r) {
	queue <int> q;
	memset(scnt, 0, sizeof(scnt));
	memset(vis, 0, sizeof(vis));
	for (int i = 1; i <= n; i++) dis[i] = INF;
	q.push(1);
	dis[1] = 0.0, vis[1] = 1;
	while (!q.empty()) {
		int ans = q.front();
		q.pop();
		scnt[ans]++, vis[ans] = 0;
		if (scnt[ans] >= n) return true;
		for (int i = head[ans]; i != -1; i = e[i].next) {
			double sum = e[i].w * r - val[e[i].v];  // 更新权值
			if (dis[e[i].v] > dis[ans] + sum) {
				dis[e[i].v] = dis[ans] + sum;
				if (!vis[e[i].v]) {
					vis[e[i].v] = 1;
					q.push(e[i].v);
				}
			} 
		}
	}
	return false;
}

int main()
{
	cin >> n >> m;
	memset(head, -1, sizeof(head));
	for (int i = 1; i <= n; i++) scanf("%d", &val[i]); // 点权值
	for (int i = 0; i < m; i++) {
		int ui, vi, wi;
		scanf("%d%d%d", &ui, &vi, &wi);
		add(ui, vi, wi);
	}
	double l = 0, r = INF * 1.0, mid;
	for (int i = 1; i <= 100; i++) {  // 二分查找答案
		mid = (l + r) / 2;
		if (spfa(mid)) l = mid; //有负环说明答案在右边
		else r = mid;  
	}
	printf("%.2f\n", mid);
	return 0;
}

K-Gourmet Grazers  

 

题目描述

Like so many others, the cows have developed very haughty tastes and will no longer graze on just any grass. Instead, Farmer John must purchase gourmet organic grass at the Green Grass Grocers store for each of his N (1 ≤ N ≤ 100,000) cows.
Each cow i demands grass of price at least Ai (1 ≤ Ai ≤ 1,000,000,000) and with a greenness score at least Bi (1 ≤ Bi ≤ 1,000,000,000). The GGG store has M (1 ≤ M ≤ 100,000) different types of grass available, each with a price Ci (1 ≤ Ci ≤ 1,000,000,000) and a greenness score of Di (1 ≤ Di ≤ 1,000,000,000). Of course, no cow would sacrifice her individuality, so no two cows can have the same kind of grass.
Help Farmer John satisfy the cows' expensive gourmet tastes while spending as little money as is necessary.

输入描述:

* Line 1: Two space-separated integers: N and M.
* Lines 2..N+1: Line i+1 contains two space-separated integers: Ai and Bi
* Lines N+2..N+M+1: Line i+N+1 contains two space-separated integers: Ci and Di

输出描述:

* Line 1: A single integer which is the minimum cost to satisfy all the cows. If that is not possible, output -1.

示例1

输入

 

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

输出

 

12

说明

Cow 1 eats grass 2 at cost 2, cow 2 eats grass 3 at cost 4, cow 3 eats grass 6 at cost 2, and cow 4 eats grass 7 at cost 4, for a total cost of 12.

题目大意 : 输入N头牛, 每头牛有两个权值,分别为期望的花费和期望的美味值, 有M种食物, 每种食物对应各自的花费与美味值,如果存在一种方案, 可以满足每头牛, 输出最小花费, 否则输出 -1

思路 : 先按美味值和花费从大到小排序, 美味值优先级高,然后从第一头牛开始, 将美味值大于等于该牛期望的食物的花费加入set, 再二分查找最小的大于该牛期望的花费, 过程中如果有一个不符合条件, 直接退出输出-1

AC代码 :

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

struct node
{
	ll x, y;
}e[MAXN], p[MAXN];
bool cmp(node a, node b) {
	if (a.y == b.y) return a.x > b.x;
	else return a.y > b.y;
}
ll n, m, ans, flag = 1;
multiset <ll> st;

int main()
{
	cin >> n >> m;
	for (ll i = 1; i <= n; i++) scanf("%lld%lld", &e[i].x, &e[i].y);
	for (ll i = 1; i <= m; i++) scanf("%lld%lld", &p[i].x, &p[i].y);
	sort(e + 1, e + n + 1, cmp), sort(p + 1, p + m + 1, cmp); // 美味值优先级大
	ll j = 1; // 如果前面的牛都满足, 后面的牛一定也满足
	for (ll i = 1; i <= n; i++) {
		for (; j <= m; j++) {
			if (p[j].y >= e[i].y) {
				st.insert(p[j].x);
			}
			else break;
		}
		multiset <ll> ::iterator it;
		it = st.lower_bound(e[i].x);
		if (it == st.end()) { flag = 0; break; } // 不存在直接退出
		else {
			ans += *it;
			st.erase(it);
		}
	}
	if (flag) cout << ans << endl;
	else cout << -1 << endl;
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值