Educational Codeforces Round 138 (Rated for Div. 2)

A:思维

题意:给一定的N*N的板子,里面放有一些乌鸦,这些乌鸦会攻击自己的所在行与所在列,问给定一个数量的乌鸦,问是否能够移动某只乌鸦,使得形成和平局面?

方法:我们发现,N*N的板子,因为乌鸦会攻击所在行与所在列,所以要形成和平局面,则最多只能放N只乌鸦,如果多余了N只,那么肯定不会形成和平局面。所以,这题只跟板子的大小和乌鸦的数量有关。

代码: 

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10;

inline void solve(){
	    int n,m;cin>>n>>m;
	    for(int i=1;i<=m;i++){
	    	int x,y;cin>>x>>y;
		}
		if(m<n)cout<<"YES\n";
		else cout<<"NO\n";
}

signed main(){
	int T;cin>>T;
	while(T--) solve();
}

B:贪心

 题意:给定N个具有一定顺序排列的怪物,这个怪物本身有血量,还有一个技能,就是在这个怪物死后,发动这个技能会使他左右两边的怪物加上一定的血量。定义怪物的血量为HP的话,那么杀死这个怪物所用的时间就需要HP秒,这一个怪物死后,就消失了。他左右的邻居就相邻了。

 问如何一个一个的杀完所有的怪物使得用的时间最短?

方法:因为杀死一个怪物,它的左右邻居都会加上一定血量,那么要想所有怪物的血量加的最少,则应该从第一个或者最后一个怪物开始杀起,因为他们的邻居只有1个,这样尽可能少的给怪物加血量。我们知道,杀完所有怪物(若所有怪物的加血技能都加0滴血),那么所需要的时间,就是所有怪物的血量和:SUM。若所有怪物的加血技能都加不为0的血量时,则所需要的最少时间一定是SUM+(N-1)个怪物的加血量。因为最后一个怪物死后,它的加血技能没有用,所以我们最优的方案一定是将加血量最多的怪物放在最后一个消灭。

代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10;

inline void solve(){
	    int res=0,maxx=0;
	    int n;cin>>n;
	    for(int i=1;i<=n;i++){
	    	int x;cin>>x;
	    	res+=x;
		}
		for(int i=1;i<=n;i++){
			int x;cin>>x;
			res+=x;
			maxx=max(maxx,x);
		}
		cout<<res-maxx<<"\n";
}

signed main(){
	int T;cin>>T;
	while(T--) solve();
}

C:暴力+贪心 or(二分+贪心)

题意:有n个数,Alice和Bob玩游戏。游戏进行k轮,每一轮Alice必须消除一个小于等于 k−i+1 的数,在消除之后,如果数组还有元素的话Bob需要对一个数增加 k−i+1 ,求Alice在保证自己在k轮内都能消除数的前提下,最多进行的轮次。

分析:Alice每消除一个数,Bob就会在剩余数组中选择一个数加k-i+1。随着轮次的增加,Alice消除的数是越来越小的。这里考虑一下贪心策略。

设想如果Bob选择的是数组中最大的数,那么Alice就肯定不会消除完所有的数,那么要想使得轮次更多,Bob选择数组中最小的数进行操作即可。

这里解释一下Bob的选择操作:为什么每次选最小数会使轮次增加?

选择最大的数进行操作是肯定不行的,那么选择次大数呢?这里不妨反演一遍,如果Bob每次都操作最小的数,那么最小数每次都在增大,则就一定会使轮次增大。

代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,a[101];

inline bool pd(int k){
	int l=1,r=n;
	for(int i=1;i<=k;i++){
		while(a[r]>k-i+1) r--;
//如果一开始就是小于最大值的话,我们就减减,为的是让这个k不满足pd
		if(l>r) return false;//说明Bob的操作次数比Alice多,则就不可能满足pd
		l++,r--;//Alice从右往左操作,Bob从左往右操作
	}
	return true;
}

inline void solve(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	sort(a+1,a+1+n);
	int ans=0;
	for(int i=1;i<=n;i++){//为什么要在1-n范围找呢?因为k-i+1的最小值只能为1而不能为0
		if(pd(i)) ans=i;
	}
	cout<<ans<<"\n";
}

signed main(){
	int T;cin>>T;
	while(T--) solve();
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值