2024牛客寒假算法基础集训营1

文章目录

  • A-DFS搜索
  • B-关鸡
  • C-按闹分配
  • E-本题又主要考察了贪心
  • G-why买外卖
  • H-01背包,但是bit_
  • [I-It's bertrand paradox. Again!](https://ac.nowcoder.com/acm/contest/67741/I)
  • L-要有光
  • M-牛客老粉才知道的秘密

A-DFS搜索

#include
#define endl '\n'
#define int long long
using namespace std;
int n;
string s;
string tmp="DFS";
string tt="dfs";
void solve() {
	cin>>n;
	cin>>s;
	int idx=0;
	for(int i=0;i<n;i++){
		if(s[i]==tmp[idx]) idx++;
	}
	int pos=0;
	for(int i=0;i<n;i++){
		if(s[i]==tt[pos]) pos++;
	}
	if(idx==3) cout<<1<<' ';
	else cout<<0<<' ';
	if(pos==3) cout<<1<<endl;
	else cout<<0<<endl;
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

B-关鸡

左半边有没有着火点,右半边有没有着火点,(2,0)有没有着火点

左半边有没有被堵死,右半边有没有被堵死

可以用set存下所有位置,然后对于第一行的(1,y),看(2,y-1),(2,y),(2,y+1)有没有着火点,以此判断左半边和右半边有没有被堵死

#include
#define endl '\n'
#define int long long
using namespace std;
typedef pair<int,int>PII;
int n;
int dy[3]={-1,0,1};
void solve() {
	cin>>n;
	bool left=false,right=false,mid=false;//左半边有没有着火点,右半边有没有着火点,(2,0)有没有着火点
	bool leftdusi=false,rightdusi=false;//左半边有没有被堵死,右半边有没有被堵死
	set<PII>s1,s2;//s1存放左半边的着火点坐标,s2存放右半边的着火点坐标
	for(int i=0;i<n;i++){
		int r,c;
		cin>>r>>c;
		if(c<0){
			s1.insert({r,c});
			left=true;
		}
		else if(c==0){
			s1.insert({r,c});
			s2.insert({r,c});
			mid=true;
		}
		else{
			s2.insert({r,c});
			right=true;
		}
	}
	if(n==0){
		cout<<3<<endl;
		return;
	}
	for(auto v:s1){//枚举左半边的着火点
		int x=v.first,y=v.second;
		if(x==2) continue;
		for(int i=0;i<3;i++){
			int ty=y+dy[i];
			if(ty<-1e9) continue;
			if(s1.count({2,ty})){
				leftdusi=true;
			}
		}
		if(leftdusi) break;
	}
	for(auto v:s2){//枚举右半边的着火点
		int x=v.first,y=v.second;
		if(x==2) continue;
		for(int i=0;i<3;i++){
			int ty=y+dy[i];
			if(ty>1e9) continue;
			if(s2.count({2,ty})){
				rightdusi=true;
			}
		}
		if(rightdusi) break;
	}
//	cout<
//	cout<
	if(leftdusi&&rightdusi) cout<<0<<endl;//左右两边都被堵死
	else if(leftdusi){//只有左边被堵死
		if(right) cout<<1<<endl;//右边没被堵死,但有至少一个着火点
		else if(mid) cout<<1<<endl;
		else cout<<2<<endl;
	}
	else if(rightdusi){//只有右边被堵死
		if(left) cout<<1<<endl;
		else if(mid) cout<<1<<endl;
		else cout<<2<<endl;
	}
	else{//如果两边都没堵死
		if(s1.count({1,-1})&&s2.count({1,1})) cout<<1<<endl;
		else if(s1.count({1,-1})||s2.count({1,1})) cout<<2<<endl;
		else if((left&&right)||mid) cout<<2<<endl;
		else cout<<3<<endl;
	}
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

C-按闹分配

#include
#define endl '\n'
#define int long long
using namespace std;
const int N=1e5+10;
int t[N];
int tt[N];
int n,q,tc;
void solve() {
	cin>>n>>q>>tc;
	int sum=0;
	for(int i=1;i<=n;i++) cin>>t[i];
	sort(t+1,t+1+n);
	for(int i=1;i<=n;i++){
		sum+=t[i];
		tt[i]=sum;
	}
//	for(int i=1;i<=n;i++) cout<
//	cout<
	while(q--){
		int m;
		cin>>m;
		m/=tc;
		if(m>=n) m=n;
		cout<<tt[n-m]+tc<<endl;
	}
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
//    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

E-本题又主要考察了贪心

数据比较小,直接暴力,dfs

#include
#define endl '\n'
#define int long long
using namespace std;
typedef pair<int,int>PII;
const int N=15;
int a[N];
int n,m;
int res;
int score;
vector<PII>ans;
void dfs(int u){
	if(u==(int)ans.size()){
		vector<int>c;
//		for(int i=1;i<=n;i++) cout<
//		cout<
		for(int i=1;i<=n;i++) c.push_back(a[i]);
//		for(int i=0;i
//		cout<
		sort(c.begin(),c.end());
		reverse(c.begin(),c.end());
//		for(int i=0;i
//		cout<
//		cout<
		for(int i=0;i<n;i++){
			if(score==c[i]){
				res=min(res,i+1);
				break;
			}
		}
		return;
	}
	int x=ans[u].first,y=ans[u].second;
	int tmp=a[x];
	a[x]+=3;
	dfs(u+1);
	a[x]=tmp;
	tmp=a[y];
	a[y]+=3;
	dfs(u+1);
	a[y]=tmp;
	int tmp1=a[x],tmp2=a[y];
	a[x]++;
	a[y]++;
	dfs(u+1);
	a[x]=tmp1;
	a[y]=tmp2;
}
void solve() {
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>a[i];
	score=a[1];
	ans.clear();
	for(int i=0;i<m;i++){
		int x,y;
		cin>>x>>y;
		if(x==1||y==1) a[1]+=3,score+=3;
		else ans.push_back({x,y});
	}
//	for(int i=1;i<=n;i++) cout<
//	cout<
	res=2e9;
	dfs(0);
	cout<<res<<endl;
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

G-why买外卖

#include
#define endl '\n'
#define int long long
using namespace std;
typedef pair<int,int>PII;
int n,m;
void solve() {
	cin>>n>>m;
	vector<PII>ans;
	int sum=0;
	for(int i=0;i<n;i++){
		int a,b;
		cin>>a>>b;
		sum+=b;
		ans.push_back({a,b});
	}
	sort(ans.begin(),ans.end());
	reverse(ans.begin(),ans.end());
	for(int i=0;i<n;i++){
		if(ans[i].first-sum<=m){
			cout<<m+sum<<endl;
			return;
		}
		sum-=ans[i].second;
	}
	cout<<m<<endl;
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

H-01背包,但是bit_

或上的和要小于等于m

假设m的二进制为100101101

首先,如果最后或起来的值刚好为m,肯定是合法的,如果m或上一个数还是等于m的话,那么就可以或上

然后,考虑最后或起来是比m小的值,那么肯定需要把某位1变成0,这样才能变小,但是想要能或上的数很多,那么1肯定要多,所以把该位后面的位全变成1,这样仍然是小于m的,是合法的,即为m1,如果m1或上一个数还是等于m1的话,那么就可以或上

同理,遍历每一个1,按照以上操作,都可以得到一个m1,是小于m的,是合法的

在这么多种情况中,取最优的就行

#include
#define endl '\n'
#define int long long
using namespace std;
const int N=1e5+10;
int v[N],w[N];
int n,m;
void solve() {
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>v[i]>>w[i];
	int ans=0;
	int sum=0;
	for(int i=1;i<=n;i++){
		if((m|w[i])==m) sum+=v[i];
	}
	ans=max(ans,sum);
	int x=0;
	for(int i=60;i>=0;i--){
		if((1ll<<i)&m){//如果m的第i位为1,那么m1为第i位为0,低位全部为1
			int m1=x|((1ll<<i)-1);
			sum=0;
			for(int i=1;i<=n;i++){
				if((m1|w[i])==m1) sum+=v[i];
			}
			ans=max(ans,sum);
			x|=(1ll<<i);
		}
	}
	cout<<ans<<endl;
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

I-It’s bertrand paradox. Again!

第一个人的圆心坐标均匀分布,第二个人圆心坐标会因为r而重置,两者圆心坐标分布概率不一样

由于n为1e5,大数据,都是随机的,模拟,可以利用关于圆心坐标的指标将两者区分开来

#include
#define endl '\n'
#define int long long
using namespace std;
int random(int l,int r){
	return (long long)rand()*rand()%(r-l+1)+l;
}
int n;
void solve() {
	//bit-noob,第一个人,重新生成r
	srand((unsigned)time(NULL));//加上这个才能真正产生随机数 
	int n=100000;
	int sum=0;
	for(int i=0;i<n;i++){
		int x,y,r;
		x=random(-99,99);
		y=random(-99,99);
		do{
			r=random(1,100);
		}while(x+r>100||x-r<-100||y+r>100||x-r<-100);
		sum+=abs(x)+abs(y);
	}
	cout<<sum<<endl;
    //9984284
    //9998881
    //9997845
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
//    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}
#include
#define endl '\n'
#define int long long
using namespace std;
int random(int l,int r){
	return (long long)rand()*rand()%(r-l+1)+l;
}
int n;
void solve() {
	//buaa-noob,第二个人,重新生成x,y,r
	srand((unsigned)time(NULL));//加上这个才能真正产生随机数 
	int n=100000;
	int sum=0;
	for(int i=0;i<n;i++){
		int x,y,r;
		do{
			x=random(-99,99);
			y=random(-99,99);
			r=random(1,100);
		}while(x+r>100||x-r<-100||y+r>100||x-r<-100);
		sum+=abs(x)+abs(y);
	}
	cout<<sum<<endl;
    //8158289
    //8150800
    //8132724
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
//    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

AC代码:

#include
#define endl '\n'
#define int long long
using namespace std;
int n;
void solve() {
	cin>>n;
	int sum=0;
	for(int i=0;i<n;i++){
		int x,y,r;
		cin>>x>>y>>r;
		sum+=abs(x)+abs(y);
	}
	if(sum>9900000) cout<<"bit-noob"<<endl;
	else cout<<"buaa-noob"<<endl;
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
//    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

L-要有光

#include
#define endl '\n'
#define int long long
using namespace std;
int c,d,h,w;
void solve() {
	cin>>c>>d>>h>>w;
	cout<<3*w*c<<endl;
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

M-牛客老粉才知道的秘密

#include
#define endl '\n'
#define int long long
using namespace std;
int n;
void solve() {
	cin>>n;
	if(n%6==0) cout<<n/6<<endl;
	else cout<<n/6*2<<endl;
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

你可能感兴趣的:(牛客寒假训练营,算法,深度优先,图论,c++,数据结构)