NOIP2005年提高組複賽上機試題

A. 誰拿了最多獎學金

某校的慣例是在每學期的期末考試之後發放獎學金。發放的獎學金共有五種,獲取的條件各自不同:

  1. 院士獎學金,每人8000元,期末平均成績高於80分(>80),並且在本學期內發表1篇或1篇以上論文的學生均可獲得;
  2. 五四獎學金,每人4000元,期末平均成績高於85分(>85),並且班級評議成績高於80分(>80)的學生均可獲得;
  3. 成績優秀獎,每人2000元,期末平均成績高於90分(>90)的學生均可獲得;
  4. 西部獎學金,每人1000元,期末平均成績高於85分(>85)的西部省份學生均可獲得;
  5. 班級貢獻獎,每人850元,班級評議成績高於80分(>80)的學生幹部均可獲得;

只要符合條件就可以得獎,每項獎學金的獲獎人數沒有限制,每名學生也可以同時獲得多項獎學金。

例如姚林的期末平均成績是87分,班級評議成績82分,同時他還是一位學生幹部,那麼他可以同時獲得五四獎學金和班級貢獻獎,獎金總數是4850元。

現在給出若干學生的相關數據,請計算哪些同學獲得的獎金總數最高(假設總有同學能滿足獲得獎學金的條件)。

輸入格式
輸入文件的第一行是一個整數N,表示學生的總數。

接下來的N行每行是一位學生的數據,從左向右依次是姓名,期末平均成績,班級評議成績,是否是學生幹部,是否是西部省份學生,以及發表的論文數。

姓名是由大小寫英文字母組成的長度不超過20的字符串(不含空格);期末平均成績和班級評議成績都是0到100之間的整數(包括0和100);是否是學生幹部和是否是西部省份學生分別用一個字符表示,Y表示是,N表示不是;發表的論文數是0到10的整數(包括0和10)。

每兩個相鄰數據項之間用一個空格分隔。

輸出格式
輸出文件包括三行,第一行是獲得最多獎金的學生的姓名,第二行是這名學生獲得的獎金總數。

如果有兩位或兩位以上的學生獲得的獎金最多,輸出他們之中在輸入文件中出現最早的學生的姓名。

第三行是這N個學生獲得的獎學金的總數。

數據範圍
1≤N≤100
輸入樣例:
4

YaoLin 87 82 Y N 0
ChenRuiyi 88 78 N Y 1
LiXin 92 88 N N 0
ZhangQin 83 87 Y N 1

輸出樣例:

ChenRuiyi
9000
28700

AC代碼

#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 110;
int n;
struct Person
{
    string name;
    int final_score, class_score;
    char is_cadre, is_west;
    int papers;
    int money;
}p[N];

int get_money(Person a)
{
    int res = 0;
    if (a.final_score > 80 && a.papers) res += 8000;
    if (a.final_score > 85 && a.class_score > 80) res += 4000;
    if (a.final_score > 90) res += 2000;
    if (a.final_score > 85 && a.is_west == 'Y') res += 1000;
    if (a.class_score > 80 && a.is_cadre == 'Y') res += 850;
    return res;
}

int main()
{
    cin >> n;
    int sum = 0;
    for (int i = 0; i < n; i ++ )
    {
        cin >> p[i].name;
        cin >> p[i].final_score >> p[i].class_score;
        cin >> p[i].is_cadre >> p[i].is_west;
        cin >> p[i].papers;
        p[i].money = get_money(p[i]);
        sum += p[i].money;
    }
    int t = 0;
    for (int i = 1; i < n; i ++ )
    {
    	if (p[i].money > p[t].money)
    	{
    		t = i;
    	}
    }
    cout << p[t].name << endl;
    cout << p[t].money << endl;
    cout << sum << endl;
    return 0;
}

B. 過河

在河上有一座獨木橋,一隻青蛙想沿着獨木橋從河的一側跳到另一側。

在橋上有一些石子,青蛙很討厭踩在這些石子上。

由於橋的長度和青蛙一次跳過的距離都是正整數,我們可以把獨木橋上青蛙可能到達的點看成數軸上的一串整點:0,1,……,L(其中L是橋的長度)。

座標爲0的點表示橋的起點,座標爲L的點表示橋的終點。

青蛙從橋的起點開始,不停的向終點方向跳躍。

一次跳躍的距離是S到T之間的任意正整數(包括S,T)。

當青蛙跳到或跳過座標爲L的點時,就算青蛙已經跳出了獨木橋。

題目給出獨木橋的長度L,青蛙跳躍的距離範圍S,T,橋上石子的位置。

你的任務是確定青蛙要想過河,最少需要踩到的石子數。

輸入格式
輸入文件的第一行有一個正整數L,表示獨木橋的長度。

第二行有三個正整數S,T,M,分別表示青蛙一次跳躍的最小距離,最大距離,及橋上石子的個數。

第三行有M個不同的正整數分別表示這M個石子在數軸上的位置(數據保證橋的起點和終點處沒有石子)。

所有相鄰的整數之間用一個空格隔開。

輸出格式
輸出文件只包括一個整數,表示青蛙過河最少需要踩到的石子數。

數據範圍
1≤L≤109,
1≤S≤T≤10,
1≤M≤100
輸入樣例:

10
2 3 5
2 3 5 6 7

輸出樣例:

2

AC代碼

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 10005, M = 110;
int L, S, T, n;
int f[N], w[N], stones[M];
int main()
{
	scanf("%d%d%d%d", &L, &S, &T, &n);
	for (int i = 1; i <= n; i++)
	{
		scanf("%d", &stones[i]);
	}
	sort(stones + 1, stones + n + 1);
	if (S == T)
	{
		int res = 0;
		for (int i = 1; i <= n; i++)
		{
			if (stones[i] % S == 0)
			{
				res++;
			}
		}
		printf("%d\n", res);
		return 0;
	}
	for (int i = 1, last = 0, offset = 0; i <= n; i++)
	{
		if (stones[i] - last > 100)
		{
			offset += stones[i] - 100 - last;
		}
		last = stones[i];
		stones[i] -= offset;
	}
	for (int i = 1; i <= n; i++)
	{
		w[stones[i]] = 1;
	}
	L = stones[n] + 10;
	for (int i = 1; i <= L; i++)
	{
		f[i] = 0x3f3f3f3f;
		for (int j = S; j <= T; j++)
		{
			if (i >= j)
			{
				f[i] = min(f[i], f[i - j] + w[i]);
			}
		}
	}
	printf("%d\n", f[L]);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章