SICNU ACM 2020级 4月训练赛——题解

文章目录

A

dfs求全排列,还是没有重复元素的全排列,很基础了
具体点这里看yht写的

B

很简单的贪心,每一次选剩下的重量最小的两个合成一堆就行了
可以用stl里面的priority_queue,也可以直接sort

优先队列做法

#include<bits/stdc++.h>
using namespace std;
int main()
{
    priority_queue<int,vector<int>,greater<int>> q;
    int n;
    cin>>n;
    for(int i=0;i<n;i++)
    {
        int x;cin>>x;
        q.push(x);
    }
    int res = 0;
    while(q.size()>1)
    {
        auto t1 = q.top();
        q.pop();
        
        auto t2 = q.top();
        q.pop();
        
        res+=t1+t2;
        q.push(t1+t2);
    }
    cout<<res;
    
}

直接sort

#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof a)
#define sd second
#define endl '\n'
#define N 200009
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
int a[N];
int main()
{
	
	int n;
	cin>>n;
	for(int i=0; i<n; i++)
	{
		scanf("%d",&a[i]);
	}
	sort(a,a+n);
	ll ans=0;
	for(int i=1; i<n; i++)
	{
		a[i]=a[i]+a[i-1];
		ans+=a[i];
		sort(a+i,a+n);
	}
	cout<<ans<<endl;
	return 0;
 } 

C

汉诺塔游戏,两种做法
模拟汉诺塔的过程即可
定义hanio(n,a,b,c)函数:将当前的在a上的n个盘子通过b移动到c去。不明白hanio函数的同学,建议手动模拟下只有2个盘子的情况,或者网上看看hanio的讲解

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
int ans;
void hanio(int n,char a,char b,char c)
{
	if(n==0) return ;
	else
	{
		hanio(n-1,a,c,b);
		ans++;
		hanio(n-1,b,a,c);
	}
}
int main()
{
	int n;
	cin>>n;
	hanio(n,'a','b','c');
	cout<<ans<<endl;
	return 0;
}

:递推公式
设f(n)表示有n个盘子时的最小移动次数
对于在a上的n个盘子我们,可以先将n-1个盘子 ‘移动’ 到b, 需要f(n-1)步,
然后将第n个移动到c, 需要1步,最后将n-1个盘子移动到c,需要f(n-1)步
所以:f(n)=2*f(n-1)+1,等式两边加1,变形为f(n)+1=2(f(n-1)+1), 高中等比数列公式,所以f(n)=2^n-1

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
ll qpow(ll x,ll k)
{
	ll res=1;
	while(k)
	{
		if(k&1) res*=x;
		k>>=1;
		x*=x;
	}
	return res;
}
int main()
{
	int n;
	cin>>n;
	cout<<qpow(2,n)-1<<endl;
	return 0;
}

D

考了3次的归并排序求逆序对,好好学吧,如果你现在觉得归并排序没用,只能说明你做题做少了,等真正需要用的时候别后悔

E

这道题,由于ai<=2500000, 那么ai+aj最大为5000000,根据抽屉原理,所以我们只要枚举到5000000+1种结果,必然有两个元素相等。那么我们直接双重for循环枚举即可,开个map,存下和以及下标i和j,一旦满足条件就输出,这样也不会超时了,因为最大才5e6+1次枚举

参考代码

#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof a)
#define sd second
#define ft first
#define endl '\n'
using namespace std;
typedef pair<int,int> PII;
const int N = 2e6+9;
int a[N];
map<int,PII> mp;
int main()
{
	int n;
	cin>>n;
	for(int i=0; i<n; i++)
	{
		scanf("%d",a+i);
	}
	for(int i=0; i<n; i++)
	{
		for(int j=i+1; j<n; j++)
		{
			int sum=a[i]+a[j];
			//查找sum是否存在 
			if(mp.find(sum)==mp.end())
			{
				
				mp[sum].ft=i,mp[sum].sd=j;
			}
			else if(mp[sum].ft!=i&&mp[sum].ft!=j&&mp[sum].sd!=i&&mp[sum].sd!=j)
			{
				
				cout<<i+1<<" "<<j+1<<" "<<mp[sum].ft+1<<" "<<mp[sum].sd+1<<endl;
				return 0;
			}
			
		}
	}
	puts("-1");
	return 0;
 }

F

bfs板子题目,没多少思维,看看代码即可

#include<bits/stdc++.h>
using namespace std;
 
const int N=5e2+10;
char ma[N][N];
bool vis[N][N];
int dx[4]={0,0,-1,1};
int dy[4]={1,-1,0,0};
/***************/
//int prex[N][N];
//int prey[N][N];
/***************/
 
struct asd{
	int x,y;
	int step;
};
int n,m;
 
int BFS()
{
	asd now,nex;
	queue<asd>q;
	memset(vis,false,sizeof(vis));
	now.x=0;
	now.y=0;
	now.step=0;
	/********************/
	//prex[0][0]=-1;
	//prey[0][0]=-1;
	/********************/
	vis[0][0]=true;
	q.push(now);
	while(!q.empty())
	{
		now=q.front();q.pop();
		int st=ma[now.x][now.y]-'0';
		if(now.x==n-1&&now.y==m-1)
			return now.step;
		for(int i=0;i<4;i++)
		{
			int x=now.x+dx[i]*st;
			int y=now.y+dy[i]*st;
			if(x<0||y<0||x>=n||y>=m||vis[x][y]||(x==now.x&&y==now.y))
				continue;
			nex.x=x;
			nex.y=y;
			/******************/
			//prex[x][y]=now.x;
			//prey[x][y]=now.y;
			/******************/
			vis[x][y]=true;
			nex.step=now.step+1;
			q.push(nex);
		}
	}
	return -1;
}
 
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=0;i<n;i++)
		scanf("%s",ma[i]);
	printf("%d\n",BFS());
	/*****************/
	//int x=n-1,xx;
	//int y=m-1,yy;
	//while(x!=-1&&y!=-1)
	//{
	//	printf("%d %d\n",x,y);
	//	xx=prex[x][y];
	//	yy=prey[x][y];
	//	x=xx;y=yy;
	//}
	/******************/
	return 0;
}

留言

这次比赛看到有同学进步,我真的还是很开心,给进步的同学点个赞。也有同学打得不好,没得事,我也爆零过,如果真想搞acm,就不要怕,努力点下次就打好了,如果不想搞了就转方向就好了,每年剩下的人都很少,理解。马上蓝桥和天梯就开始了,好好准备吧,你们当中总会有人越来越优秀的~

posted @ 2022-08-28 08:43  翔村亲亲鸟  阅读(11)  评论(0编辑  收藏  举报