USACO铜组测试4

USACO铜组测试4

T1-奶牛的学术圈 I

D7gk7. 奶牛的学术圈 I
时间限制:1.0s 内存限制:256.0MB
输入文件名:prob1.in 输出文件名:prob1.out
试题来源:USACO
问题描述
由于对计算机科学的热爱,以及有朝一日成为 「Bessie 博士」的诱惑,奶牛 Bessie 开始攻读计算机科学博士学位。经过一段时间的学术研究,她已经发表了 N 篇论文(),并且她的第 i 篇论文得到了来自其他研究文献的 ci 次引用()。
Bessie 听说学术成就可以用 h 指数来衡量。h 指数等于使得研究员有至少 h 篇引用次数不少于 h 的论文的最大整数 h。例如,如果一名研究员有 4 篇论文,引用次数分别为 (1,100,2,3),则 h 指数为 2,然而若引用次数为 (1,100,3,3) 则 h 指数将会是 3。
为了提升她的 h 指数,Bessie 计划写一篇综述,并引用一些她曾经写过的论文。由于页数限制,她至多可以在这篇综述中引用 L 篇论文(),并且她只能引用每篇她的论文至多一次。
请帮助 Bessie 求出在写完这篇综述后她可以达到的最大 h 指数。
注意 Bessie 的导师可能会告知她纯粹为了提升 h 指数而写综述存在违反学术道德的嫌疑;我们不建议其他学者模仿 Bessie 的行为。
输入格式
输入的第一行包含 N 和 L。
第二行包含 N 个空格分隔的整数 c1,…,cN。
输出格式
输出写完综述后 Bessie 可以达到的最大 h 指数。
输入样例
4 0
1 100 2 3
输出样例
2
样例说明
Bessie 不能引用任何她曾经写过的论文。上文中提到,(1,100,2,3) 的 h 指数为 2。
输入样例
4 1
1 100 2 3
None
输出样例:
3
样例说明
如果 Bessie 引用她的第三篇论文,引用数会变为 (1,100,3,3)。上文中提到,这一引用数的 h 指数为 3。

额,首先,因为我们只能引用同一篇文章一遍,所以我们要找到未引用前最大指数,而答案只可能是该数+1(引用文章)或本身(不引用)

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

int n,l,c[100010],h;

void work(){
	cin>>n>>l;
	for(int i=1;i<=n;++i){
		cin>>c[i];
	}
	sort(c+1,c+1+n);
	int ii=n;
	while(c[ii]>=n-ii+1)
		--ii;
	h=n-ii;
	if(c[ii]==h){
		for(int i=n;i>=ii;--i)
			if(c[i]==h)--l;
		if(l>=0)cout<<h+1<<endl;
		else cout<<h<<endl;
	}
	else cout<<h<<endl;
}

int main(){
	freopen("prob1.in","r",stdin);
	freopen("prob1.out","w",stdout);
	work();
	fclose(stdin);
	fclose(stdout);
	return 0;
}

T2-奶牛的学术圈 II

Do2fk. 奶牛的学术圈 II
时间限制:1.0s 内存限制:256.0MB
输入文件名:prob2.in 输出文件名:prob2.out
试题来源:USACO
问题描述
Bessie 正在申请计算机科学的研究生,并取得了一所久负盛名的计算机科学实验室的面试通知。然而,为了避免冒犯任何人,Bessie 有意先确定实验室的 N 名现有成员的相对资历(1≤N≤100)。没有两名实验室成员的资历相同,但确定他们的资历深浅可能并不好办。为此,Bessie 将会对实验室的出版物进行调查。
每份出版物均包含一个作者列表,为所有 N 名实验室成员的一个排列。列表按每名实验室成员对这篇文章的贡献降序排列。如果多名研究员的贡献相等,则按字典序排列。由于更有资历的实验室成员负有更多的管理责任,更有资历的研究员从不会比资历较浅的研究员做出更多的贡献。
例如,在一个由资历较浅的学生 Elsie、资历较深的教授 Mildred、以及十分资深的教授 Dean 组成的实验室中,可能存在一篇论文 Elsie-Mildred-Dean,如果他们做出了不等的贡献(也就是说,Elsie 做出的贡献比 Mildred 更多,Mildred 比 Dean 更多)。然而,也有可能存在一篇论文 Elsie-Dean-Mildred,如果 Mildred 和 Dean 做出了相等的贡献,而 Elsie 做出了更多的贡献。
给定实验室的 K 份出版物(1≤K≤100),对于实验室中每对研究员,如果可能的话帮助 Bessie 判断其中谁的资历更深。
输入格式
输入的第一行包含两个整数 K 和 N。
第二行包含 N 个空格分隔的字符串,为实验室的成员的名字。每个字符串均由小写字母组成,且至多包含 10 个字符。
以下 K 行,每行包含 N 个空格分隔的字符串,表示一份出版物的作者列表。
输出格式
输出 N 行,每行 N 个字符。在第 i 行内,对于所有 j≠i,当可以确定第 i 名成员比第 j 名成员资历更深时字符 j 为 1,当可以确定第 i 名成员比第 j 名成员资历更浅时字符 j 为 0,当不能由给定的出版物确定时为 ?。
第 i 行的字符 i 应为 B,因为这是 Bessie 最喜欢的字母。
输入样例
1 3
dean elsie mildred
elsie mildred dean
输出样例
B11
0B?
0?B
None
样例说明
在这个样例中,单独一份论文 elsie-mildred-dean 并不能提供足够的信息判断 Elsie 比 Mildred 资历更深或更浅。然而,我们可以推断出 Dean 一定比这两名研究员资历更深,从而资历排序为 Elsie<Mildred<Dean 和 Mildred<Elsie<Dean 均是可能的。
输入样例
2 3
elsie mildred dean
elsie mildred dean
elsie dean mildred
输出样例
B00
1B0
11B
样例说明
在这个样例中,唯一能与两篇论文相一致的资历排序为Elsie<Mildred<Dean,这是因为基于第一个样例所提供的信息,第二篇论文可以帮助我们推断出 Mildred 比 Elsie 的资历更深。

总的来说,要根据一份名单判断资历的规则是这样:
1.a的字典序大于b的字典序却排在了b前面,可以判断
2.字符串按字典序排,无法判断
再稍微精进一下:
1.区间有序,无法判断
2.区间无序,可以判断

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

int n,k;
char vh[110][110];
string name[110],s[110][110];

int check(int i){
	int findj,findk;
	for(int j=1;j<=n;++j){
		for(int ii=1;ii<=n;++ii){
			if(name[ii]==s[i][j])findj=ii;
		}
		for(int k=j;k<=n;++k){
			for(int ii=1;ii<=n;++ii){
				if(name[ii]==s[i][k])findk=ii;
			}
			if(vh[findj][findk]!='?')continue;
			if(findj==findk){
				vh[findj][findk]=vh[findk][findj]='B';
				continue;
			}
			int a=j,b=k;
			if(k>j){
				a=k;
				b=j;
			}
			bool bl=1;
			for(int p=b+1;p<=a;++p)
				if(s[i][p-1]>s[i][p]){
					bl=0;
					break;
				}
			if(!bl){
				if(k>j){
					vh[findk][findj]='1';
					vh[findj][findk]='0';
				}
				else{
					vh[findk][findj]='0';
					vh[findj][findk]='1';
				}
			}
		}
	}
}

void readp(){
	cin>>k>>n;
	for(int i=1;i<=n;++i)
		cin>>name[i];
	for(int i=1;i<=k;++i)
		for(int j=1;j<=n;++j)
			cin>>s[i][j];
	for(int i=1;i<=n;++i)
		for(int j=1;j<=n;++j)
			vh[i][j]='?';
} 

void print(){
	for(int i=1;i<=n;++i){
		for(int j=1;j<=n;++j)
			cout<<vh[i][j];
		cout<<endl;
	}
}

int main(){
	freopen("prob2.in","r",stdin);
	freopen("prob2.out","w",stdout);
	readp();
	for(int i=1;i<=k;++i)
		check(i);
	print();
	fclose(stdin);
	fclose(stdout);
	return 0;
}

当然也可以用map,这样可以减少一层查找的循环,其实是我不会map

T3-奶牛的学术圈 IIl

D7a0d. 奶牛的学术圈 III
时间限制:1.0s 内存限制:256.0MB
输入文件名:prob3.in 输出文件名:prob3.out
试题来源:USACO
问题描述
Bessie 是一位忙碌的计算机科学研究生。然而,即使是研究生也需要交友。因此,Farmer John 开设了一片草地,目的是为了帮助 Bessie 与其他奶牛建立持久的友谊。
Farmer John 的草地可以被看做是由正方形方格组成的巨大二维方阵(想象一个巨大的棋盘)。每个方格用如下字符标记:
C,如果这个方格中有一头奶牛。
G,如果这个方格中有草。
.,如果这个方格既没有奶牛也没有草。
对于两头想要成为朋友的奶牛,她们必须选择在一个与她们均水平或竖直方向上相邻的有草方格见面。在这个过程中,她们会在这个有草方格中吃草,所以之后的奶牛不能再使用这个方格作为见面地点。一头奶牛可以与多头其他奶牛成为朋友,但是同一对奶牛不能见面并成为朋友多于一次。
Farmer John 希望有许多奶牛可以见面并成为朋友。请求出当这一活动结束时在奶牛之间可以建立的朋友关系的最大数量。
输入格式
输入的第一行包含 N 和 M(1≤N,M≤1000)。
以下 N 行每行包含一个由 M 个字符组成的字符串,表示这个草地。
输出格式
输出在这一活动结束时在奶牛之间可以建立的朋友关系的最大数量。
输入样例
4 5
.CGGC
.CGCG
CGCG.
.CC.C
输出样例
4
样例说明
如果我们用坐标 (i,j) 标记第 i 行第 j 列的奶牛,则在这个样例中于 (1,2)、(1,5)、(2,2)、(2,4)、(3,1)、(3,3)、(4,2)、(4,3) 以及 (4,5) 存在奶牛。一种使四对奶牛成为朋友的方式如下:
位于 (2,2) 和 (3,3) 的奶牛于 (3,2) 一起吃草。
位于 (2,2) 和 (2,4) 的奶牛于 (2,3) 一起吃草。
位于 (2,4) 和 (3,3) 的奶牛于 (3,4) 一起吃草。
位于 (2,4) 和 (1,5) 的奶牛于 (2,5) 一起吃草。
测试点性质
测试点 2-4 满足 N=2。
测试点 5-12 没有额外限制。

本质上来说很简单,只需要标记草周围牛的个数或牛周围草的个数就可以,但是要解决一个问题:
重复交友怎么办?
如:
GC
CG
因为“但是同一对奶牛不能见面并成为朋友多于一次。”所以答案是1非2。
但是怎么处理呢?
其实这种会导致重复的情况很具有特色,就是形成了一个“×”。(判断条件:当前位置的邻接牛个数与左上或右上方的牛个数都是2)

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

int n,m,vh[1010][1010];
char a[1010][1010];

void work(){
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j){
			if(a[i][j]=='C'){
				if(a[i-1][j]=='G')++vh[i-1][j];
				if(a[i+1][j]=='G')++vh[i+1][j];
				if(a[i][j+1]=='G')++vh[i][j+1];
				if(a[i][j-1]=='G')++vh[i][j-1];
			}
		}
}

int check(){
	int ans=0;
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j){
			if(vh[i][j]>=3)++ans;
			else if(vh[i][j]==2&&!(vh[i+1][j-1]==2&&a[i+1][j]=='C'&&a[i][j-1]=='C')&&!(vh[i+1][j+1]==2&&a[i+1][j]=='C'&&a[i][j+1]=='C'))++ans;
		}
	return ans;
}

void readp(){
	cin>>n>>m;
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			cin>>a[i][j];
}

int main(){
	freopen("prob3.in","r",stdin);
	freopen("prob3.out","w",stdout);
	readp();
	work();
	cout<<check()<<endl;
	fclose(stdin);
	fclose(stdout);
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GaoGuohao2022

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值