2020/10/31模拟赛

CSP第二轮前模拟赛

我太菜了

T1

题目描述

奶牛们对围栏的高度非常敏感。奶牛希望围栏高度既不太矮以至于他们没有安全感,也不太高以至于她们看不见围栏外的天地。所以每头奶牛都有自己喜欢的高度。奶牛有N头,每个奶牛有一个自己喜欢的高度在[1…10,000]范围里。

这对John来说是一个头疼的问题。作为一个美学观点强烈的人,他希望围栏的高度基本相同,但作为一个有同情心的人,他希望能尽可能的满足奶牛们的需求。(或许他只是一个自私的人,希望奶牛能给他多产点奶)

作为妥协,他决定将围栏的柱子做成不同的高度以满足大多数奶牛的需求(必须严格超过半数)。一个满意的条件是在所有的柱子中有它喜欢的那个高度。但同时John希望最高的柱子和最矮的柱子之间的高度差最小。请你帮他解决这个问题。

围栏的高度仅仅由柱子的高度决定。

输入格式

第1行:一个整数N。( 1 < = n < = 10000 1<=n<=10000 1<=n<=10000

第2…N+1行:一个整数 A i A_i Ai表示这头牛喜欢的高度。

输出格式
仅一行即最高的柱子和最矮的柱子之间的高度差。

样例数据

input

3
1
10
3

output

2
【样例说明】 John使用高度为1,3的柱子建围栏,使三头牛中的两头满意,而3-1=2,所以输出2。

数据规模与约定
时间限制: 1 s 1 s 1s1s 1s1s
空间限制: 256 M B 256MB 256MB

只A了这一个题QAQ

说明这个题确实水。我先开个数组存每个奶牛心仪的高度,sort排序然后因为是要大多数奶牛,所以比较第i头到第 i + ( N / 2 + 1 ) i+(N/2+1) i+N/2+1头奶牛喜欢的高度差,for循环里挨个枚举就行了。`

#include <bits/stdc++.h>
using namespace std;
long long ans=9999999,n,a[19000],m;
int main()
{
    
    freopen("height.in","r",stdin);freopen("height.out","w",stdout);
	cin>>n;
	for(int i=1;i<=n;i++)    cin>>a[i];
	sort(a+1,a+n+1);
    if(n%2==1) m=n/2+1;
    if(n%2==0) m=n/2;
    for(int i=1;i<=m;i++)
    {
    
    
    	if(a[n/2+i]-a[i]<ans) ans=a[n/2+i]-a[i];
    }
	cout<<ans;
	return 0;
}

希望csp都是这种题。

T2

题目描述

贝茜这头奶牛设计了她认为将是下一个热门的视频游戏“愤怒的奶牛”。她认为这是她完全原创的:玩家将一个弹弓射到一个一维的场景中,该场景由位于数字线上各个点的一组干草包组成。每只奶牛都有足够的力量引爆其落地地点附近的干草包。爆炸后的奶牛会引爆R范围内的干草包。我们的目的是使用一系列奶牛引爆所有的干草包。

有N捆干草包位于这一行的不同整数位置 x 1 , x 2 , . . . , x N x_1,x_2,...,x_N x1,x2,...,xN,如果一头奶牛以能量R着陆在了位置x,那么会引起半径为 R ( x − R . . R + x ) R(x-R..R+x) RxR..R+x的爆炸,并摧毁范围内的所有干草包。

一共有K头奶牛允许被用来作为炮弹,每头奶牛的能量R都相同。请帮忙决定这个最小的能量,使得用这K头奶牛可以摧毁所有的干草包。

输入格式

第一行包含两个整数 N , K ( 1 < = N < = 50 , 000 , 1 < = K < = 10 ) N,K(1<=N<=50,000,1<=K<=10) N,K(1<=N<=50,0001<=K<=10)

接下来N行,每行包含一个整数xi,表示每捆干草包的位置 ( 0 < = x i < = 1 , 000 , 000 , 000 ) (0<=xi<=1,000,000,000) (0<=xi<=1,000,000,000)

输出格式

一行一个整数,最少所需要的每头奶牛的能量值R。

样例数据

input

7 2
20
25
18
8
10
3
1

output

5
数据规模与约定
时间限制: 1 s 1 s 1s1s 1s1s
空间限制: 256 M B 256MB 256MB
万恶的奶牛

看错题了QAQ

一开始以为干草包会连锁爆炸,就想当然打成了这样的代码

#include <bits/stdc++.h>
using namespace std;
long long x[55000],n,k,r,y[50001];
int main()
{
    
    freopen("angry.in","r",stdin);freopen("angry.out","w",stdout);
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++) scanf("%d",&x[i]);
	sort(x+1,x+1+n);
	for(int i=1;i<n;i++)
	{
    
    
		y[i]=x[i+1]-x[i];
	}
	sort(y+1,y+n);
	for(int i=1;i<=k;i++)
	{
    
    
		if(y[n-1]%2==0) y[n-1]=y[n-1]/2;
	    else if(y[n-1]%2==1) y[n-1]=y[n-1]/2+1;
	    sort(y+1,y+n);
	}
	r=y[n-1];
	printf("%d",r);
	return 0;	
}

也不考虑会不会超时,最最恶心的是两组样例都过了
好家伙,直接把水稻往我胃里插
出来成绩整个人都傻了(但是不知道为啥还是得了十分)
然后就只能好好用二分写了。

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

int n,m;
const int pp=1e7;
int a[pp];

bool check(int x)
{
    
                                                
    int first=1,now=1,num=1;
    while(now<=n)
    {
    
    
        while(a[now]-a[first]<=x&&now<=n) now++;
		if(now<=n)
		{
    
    
			first=now;                                       
			num++;	
		}	
    }                                              
    if(num<=m) return 1;                            
    else return 0;                               
}   

int er()
{
    
    
	int lert=0,right=2*pp,mid;
	while(lert+1<right)
	{
    
    
		mid=(lert+right)/2;
		if(check(mid)) right=mid;
		else  lert=mid;
	}
	if(check(lert)) return lert;
	else return right;
}


int main()
{
    
    
	freopen("angry.in","r",stdin);freopen("angry.out","w",stdout);
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	cin>>a[i];
	sort(a+1,a+n+1);
	int ans=(er()+1)/2;
	printf("%d",ans);
	return 0;
}

标准的二分答案

T3

著名的龙虎斗!!!(普及组)

题目描述

轩轩和凯凯正在玩一款叫《龙虎斗》的游戏,游戏的棋盘是一条线段,线段上有 n个兵营(自左至右编号 1 ∼n),相邻编号的兵营之间相隔 1 厘米,即棋盘为长度为 n-1 厘米的线段。i 号兵营里有 cici 位工兵。

下面图 1 为 n = 6 n=6 n=6的示例:

在这里插入图片描述

轩轩在左侧,代表“龙”;凯凯在右侧,代表“虎”。 他们以 m 号兵营作为分界, 靠左的工兵属于龙势力,靠右的工兵属于虎势力,而第 m号兵营中的工兵很纠结,他们不属于任何一方。

一个兵营的气势为:该兵营中的工兵数 × 该兵营到 m 号兵营的距离;参与游戏 一方的势力定义为:属于这一方所有兵营的气势之和。

下面图 2 为 n = 6,m = 4 的示例,其中红色为龙方,黄色为虎方:

在这里插入图片描述

游戏过程中,某一刻天降神兵,共有 s 1 s_1 s1位工兵突然出现在了 p 1 p_1 p1号兵营。作为轩轩和凯凯的朋友,你知道如果龙虎双方气势差距太悬殊,轩轩和凯凯就不愿意继续玩下去了。为了让游戏继续,你需要选择一个兵营 p 2 p_2 p2,并将你手里的 s 2 s_2 s2位工兵全部派往 兵营 p 2 p_2 p2,使得双方气势差距尽可能小。

注意:你手中的工兵落在哪个兵营,就和该兵营中其他工兵有相同的势力归属(如果落在 m 号兵营,则不属于任何势力)。

输入格式

输入文件的第一行包含一个正整数n,代表兵营的数量。

接下来的一行包含 n 个正整数,相邻两数之间以一个空格分隔,第 i个正整数代 表编号为 i 的兵营中起始时的工兵数量 c i c_i ci

接下来的一行包含四个正整数,相邻两数间以一个空格分隔,分别代表 m , p 1 , s 1 , s 2 m , p 1 , s 1 , s 2 m,p_1,s_1,s_2m,p_1,s_1,s_2 m,p1,s1,s2m,p1,s1,s2

输出格式

输出文件有一行,包含一个正整数,即 p 2 p_2 p2,表示你选择的兵营编号。如果存在多个编号同时满足最优,取最小的编号。

样例数据

input1

6
2 3 2 3 2 3
4 6 5 2

output1

2

input2

6
1 1 1 1 1 16
5 4 1 1

output2

1
样例说明
样例1:见问题描述中的图 2。

双方以 m=4号兵营分界,有 s 1 s_1 s1=5 s 1 s_1 s1=5位工兵突然出现在 p 1 p_1 p1=6 p 1 p_1 p1=6号兵营。 龙方的气势为:

2×(4−1)+3×(4−2)+2×(4−3)=14

虎方的气势为:

2×(5−4)+(3+5)×(6−4)=18

当你将手中的 s2=2s2=2位工兵派往 p2=2p2=2号兵营时,龙方的气势变为:

14+2×(4−2)=18

此时双方气势相等。

样例2:

双方以 m = 5号兵营分界,有 s 1 s_1 s1=1位工兵突然出现在 p 1 p_1 p1=4号兵营。

龙方的气势为:

1×(5−1)+1×(5−2)+1×(5−3)+(1+1)×(5−4)=11

虎方的气势为:

16×(6−5)=16

当你将手中的 s2=1s2=1位工兵派往 p2=1p2=1号兵营时,龙方的气势变为:

11+1×(5−1)=15

此时可以使双方气势的差距最小。

数据规模与约定
1 < m < n , 1 ≤ p 1 ≤ n 1 < m < n , 1 ≤ p 1 ≤ n 1<m<n,1≤p1≤n1<m<n,1≤p1≤n 1mn,1p1n1mn,1p1n

对于%20 的数据,n=3,m=2,ci=1,s1,s2≤100n=3,m=2,ci=1,s1,s2≤100。

另有%20 的数据,n≤10,p1=m,ci=1,s1,s2≤100n≤10,p1=m,ci=1,s1,s2≤100。

对于%60 的数据,n≤100,ci=1,s1,s2≤100n≤100,ci=1,s1,s2≤100。

对于%80 的数据,n≤100,ci,s1,s2≤100n≤100,ci,s1,s2≤100。

对于%100 的数据,n≤105,ci,s1,s2≤109n≤105,ci,s1,s2≤109。

时间限制:1s1s
空间限制:256MB

普及组的题我都A不了,菜死我了QAQ

考试的时候就直接先把龙和虎的气势分别算出来然后比较下大小,分别试下把“天降神兵”放到弱势方的每个阵营。
然后就52了……
后来改错注意到没有算把兵加到m阵营,即不叫增员时两边气势最接近,改上去之后加了几分,然后又把所有数据都long long,又加了几分,聪明的我又在return 0前加了个特判,于是愉快地ac了!!!

#include <bits/stdc++.h>
using namespace std;
long long n,c[123456],p1,s1,p2,s2,m;
unsigned long long lo,hu,lo2,hu2;  //按照题目输入 
long long hh=99999999;  //hh记录给哪个组 
int main()
{
    
    freopen("fight.in","r",stdin);freopen("fight.out","w",stdout);
	cin>>n;
	for(int i=1;i<=n;i++) scanf("%d",&c[i]);
	scanf("%d%d%d%d",&m,&p1,&s1,&s2);
	for(int i=1;i<m;i++) lo+=(m-i)*c[i];  //lo是龙的气势 
	for(int i=m+1;i<=n;i++) hu+=(i-m)*c[i]; //hu是虎的气势 
	if(p1>m) hu+=(p1-m)*s1;  //加人 
	if(p1<m) lo+=(m-p1)*s1;  //加人 
	hh=labs(hu-lo);
	if(hu>lo)  //如果虎的气势多 
	{
    
    
	    for(int i=1;i<=m;i++) //枚举把人加到龙的每个组里或者不加 
	    {
    
    
	    	lo2=lo;
	    	lo2+=(m-i)*s2;  //加到龙的某个营 
	    	if(lo2==hu) //特判下可能加到某个营后两边气势就可以一样 
	    	{
    
    
	    		cout<<i;
	    		return 0;
	    	}
	    	else if(lo2>hu&&lo2-hu<hh)
			{
    
    
				hh=lo2-hu;
				p2=i;
			}
			else if(lo2<hu&&hu-lo2<hh)
			{
    
    
				hh=hu-lo2;
				p2=i;
			}
	    }
	}
	else if(lo>hu)
	{
    
    
		for(int i=m;i<=n;i++)
		{
    
    
			hu2=hu;
			hu2+=(i-m)*s2;
			if(lo==hu2)
			{
    
    
				cout<<i;
				return 0;
			}
			else if(lo>hu2&&lo-hu2<hh)
			{
    
    
				hh=lo-hu2;
				p2=i;
			}
			else if(lo<hu2&&hu2-lo<hh)
			{
    
    
				hh=hu2-lo;
				p2=i;
			}
		}
	}
	else if(lo==hu)  //如果两边气势一样,直接把人加到中立兵营 
	{
    
    
		cout<<m;
		return 0;
	}
	if(p2==0)
	{
    
    
		cout<<m;
		return 0;
	}
	cout<<p2;
	return 0;
}

因为这道题修改的时候找了几个大佬帮我看看,所以就特别加了注释。

T4

题目描述

这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法。大家肯定很清楚,在中国象棋中炮的行走方式是:一个炮攻击到另一个炮,当且仅当它们在同一行或同一列中,且它们之间恰好 有一个棋子。你也来和小可可一起锻炼一下思维吧!
输入格式
一行包含两个整数N,M,之间由一个空格隔开。

输出格式

总共的方案数, 答案不超过int能容纳的最大值。

样例数据

input1

1 3

output1

7

input2

3 2

output2

49

样例说明

除了3个格子里都塞满了炮以外,其它方案都是可行的,所以一共有222-1=7种方案。
数据规模与约定
30% N=1;
100% N,M<=6。
时间限制:1s1s
空间限制:256MB256MB

2009年安徽省选中国象棋(小数据版)

30分 N=1,递推也彳亍,递归也彳亍。
显然是搜索,和 彳亍皇后类似,规则彳亍皇后简单;
象棋中的炮要隔一个子才能打,所以,可以放炮的方案是每行,每列不能超过两个炮。
dfs枚举,每行放两个炮的位置,两重循环枚举,类似于八皇后,当前列也要判断当前答案是否可行。
本题得到解决。

鄙人不才,只拿了30分QAQ

猜你喜欢

转载自blog.csdn.net/ydsrwex/article/details/109407591