牛客白月赛32【题解】

https://ac.nowcoder.com/acm/contest/11163#question

拼三角【枚举】

在这里插入图片描述

#include<bits/stdc++.h> 
using namespace std;
int a[15],st[15],flag;
bool check(vector<int> ve)
{
    
    
	sort(ve.begin(),ve.end());
	return ve[0]+ve[1]>ve[2];
}
void dfs(int index)
{
    
    
	if(index==3)
	{
    
    
		vector<int>ve1,ve2;
		for(int i=0;i<6;i++)
			if(st[i]) ve1.push_back(a[i]);
			else ve2.push_back(a[i]);
		if(check(ve1)&&check(ve2)) flag=1;
		return;
	}
	for(int i=0;i<6;i++)
	{
    
    
		if(!st[i]) 
		{
    
    
			st[i]=1;
			dfs(index+1);
			st[i]=0;
		}
	}
}
int main(void)
{
    
    
	int t; cin>>t;
	while(t--) 
	{
    
    
		for(int i=0;i<6;i++) cin>>a[i];
		flag=0;
		memset(st,0,sizeof st);
		dfs(0);
		if(flag) puts("Yes");
		else puts("No");
	}
	return 0;
}

用全排列更简单。

消减整数【思维】

在这里插入图片描述
转化成二进制后一定是一连串的,中间不能有0。往前进位就行。

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

int main(void)
{
    
    
	int t; cin>>t;
	while(t--) 
	{
    
    
		int n; cin>>n;
		vector<int>ve;
		int cnt=0;
		ve.push_back(n);
		for(int i=0;i<32;i++) ve.push_back(0); 
		for(int i=0;i<32;i++)
			if(ve[i]&1) ve[i+1]+=ve[i]/2,ve[i]=ve[i]%2;
			else if(ve[i]) 
			{
    
    
				int w=ve[i]/2-1;
				ve[i+1]+=w;
				ve[i]-=w*2;
			}
		for(int i=0;i<ve.size();i++) cnt+=ve[i];
		cout<<cnt<<'\n';
	}
	return 0;
}

消灭星星【二进制枚举】

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
const int N=25;
string s[N];
int t,n,m,k;
bool check(map<char,int>mp)
{
    
    
	map<int,int>x,y;
	mp['*']=1,mp['.']=1;
	for(int i=0;i<n;i++)
	{
    
    
		bool flag=1;
		for(int j=0;j<n;j++) 
			if(mp.count(s[i][j])==0) flag=0;//该字母不可删除
		if(flag) x[i]=1;//说明这一行都是可删的
	}
	for(int i=0;i<n;i++)
	{
    
    
		bool flag=1;
		for(int j=0;j<n;j++) 
			if(mp.count(s[j][i])==0) flag=0;
		if(flag) y[i]=1;//说明这一列都是可删的
	}
	int flag=1;
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
			if(s[i][j]=='*')
			{
    
    
				if(x[i]==0&&y[j]==0) flag=0;//说明该字母所属的行和列都不可删除
			}
	return flag;
}
int main(void)
{
    
    
	cin>>t;
	while(t--)
	{
    
    
		cin>>n>>m>>k;
		for(int i=0;i<n;i++) cin>>s[i];
		vector<char>ve;
		for(int i=0;i<m;i++) ve.push_back(char('A'+i));
		//撑死删k个字母 
		bool flag=0;
		for(int i=0;i<(1<<m);i++)
		{
    
    
			map<char,int>mp;
			for(int j=0;j<m;j++)
				if(i>>j&1) mp[('A'+j)]++;
			if(mp.size()>k) continue;//最多删k个不同的字母
			if(check(mp)) flag=1;
		}
		if(flag) puts("yes");
		else puts("no");
	}
	return 0;
}

春游【贪心】

在这里插入图片描述
考虑,2人的便宜还是3人的便宜。尽可能用便宜的。
但是有一个坑点就是假如2人便宜,2人的组队后还有1个人该咋办。 是再拿一个2人船,还是拿一组2人的再加这1个用个三人船。
你会发现前面的整体很好分,但是最后的余数还得分开讨论。很麻烦。
故直接将总数减去一个值,将前面的按最优分组。剩下的余数直接暴力即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long int LL;
int main(void)
{
    
    
	int t;cin>>t;
	while(t--)
	{
    
    
		LL n,a,b; cin>>n>>a>>b;
		if(a/2.0<=b/3.0)
		{
    
    
			LL cnt=max(0ll,(n-10)/2);//2人船的个数  n-10 是多拿些直接暴力的处理边界
			n=n-cnt*2;
			LL sum=cnt*a;
			LL temp=1e13;
			for(int i=0;i<=20;i++)
				for(int j=0;j<=20;j++)
					if((i*2+j*3)>=n) temp=min(temp,i*a+j*b);
			cout<<sum+temp<<'\n';
		}
		else
		{
    
    
			LL cnt=max(0ll,(n-10)/3);//3人船的个数 
			n=n-cnt*3;
			LL sum=cnt*b;
			LL temp=1e13;
			for(int i=0;i<=30;i++)
				for(int j=0;j<=30;j++)
					if((i*2+j*3)>=n) temp=min(temp,i*a+j*b);
			cout<<sum+temp<<'\n';
		}
	}
	return 0;
}

五连珠【模拟】

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
int t,a[15][15],b[15][15],op[40];
int st1[15][15],st2[15][15];
map< int,pair<int,int> >mp1,mp2;
bool f1(int x,int y)
{
    
    
	st1[x][y]=1;
	int flag=0,cnt=0;
	
	for(int i=0;i<5;i++) if(st1[i][y]) cnt++;
	if(cnt==5) flag=1;
	
	cnt=0;
	for(int i=0;i<5;i++) if(st1[x][i]) cnt++;
	if(cnt==5) flag=1;
	
	cnt=0;
	for(int i=0,j=0;i<5&&j<5;i++,j++) if(st1[i][j]) cnt++;
	if(cnt==5) flag=1;
	
	cnt=0;
	for(int i=0,j=4;i<5&&j>=0;i++,j--) if(st1[i][j]) cnt++;
	if(cnt==5) flag=1;
	return flag;
}
bool f2(int x,int y)
{
    
    
	st2[x][y]=1;
	int flag=0,cnt=0;
	
	for(int i=0;i<5;i++) if(st2[i][y]) cnt++;
	if(cnt==5) flag=1;
	
	cnt=0;
	for(int i=0;i<5;i++) if(st2[x][i]) cnt++;
	if(cnt==5) flag=1;
	
	cnt=0;
	for(int i=0,j=0;i<5&&j<5;i++,j++) if(st2[i][j]) cnt++;
	if(cnt==5) flag=1;
	
	cnt=0;
	for(int i=0,j=4;i<5&&j>=0;i++,j--) if(st2[i][j]) cnt++;
	if(cnt==5) flag=1;
	return flag;
}
int main(void)
{
    
    
	cin>>t;
	while(t--) 
	{
    
    
		for(int i=0;i<5;i++)
			for(int j=0;j<5;j++)
			{
    
    
				cin>>a[i][j];
				mp1[a[i][j]]={
    
    i,j};
			}
		for(int i=0;i<5;i++)
			for(int j=0;j<5;j++)
			{
    
    
				cin>>b[i][j];
				mp2[b[i][j]]={
    
    i,j};
			}
		memset(st1,0,sizeof st1);
		memset(st2,0,sizeof st2);
		for(int i=0;i<25;i++) cin>>op[i];
		bool flag1=0,flag2=0;
		for(int i=0;i<25;i++)
		{
    
    
			int x1=mp1[op[i]].first,y1=mp1[op[i]].second;
            int x2=mp2[op[i]].first,y2=mp2[op[i]].second;
			if(f1(x1,y1)) flag1=1;
			if(f2(x2,y2)) flag2=1;
			if(flag1||flag2) break;
		}
		if(flag1&&flag2) puts("0");
		else if(flag1) puts("1");
		else puts("2");
	}
	return 0;
}

有始有终【双向广搜】

在这里插入图片描述

#include<bits/stdc++.h> 
using namespace std;
typedef pair<int,int> PII;
const int N=110;
int st[N][N],a[N][N];
int dx[4]={
    
    -1,0,0,1},dy[4]={
    
    0,-1,1,0};
int n,m,stx,sty,edx,edy,d;
struct node{
    
    int x,y,step,id;};
int bfs(int x,int y)
{
    
    
	memset(st,0,sizeof st);
	deque<node>q; q.push_back({
    
    x,y,0,0});
	st[x][y]=1;
	while(q.size())
	{
    
    
		node temp=q.front(); q.pop_front();
		x=temp.x,y=temp.y;
        st[x][y]=1;
		if(x==edx&&y==edy) return temp.step;
		for(int i=0;i<4;i++)
		{
    
    
			int tempx=x+dx[i],tempy=y+dy[i];
			if(tempx<1||tempx>n||tempy<1||tempy>m) continue;
			if(st[tempx][tempy]) continue;
			if( abs(a[tempx][tempy]-a[x][y])>d && !temp.id )//且不是电梯
			{
    
    
				q.push_back({
    
    tempx,tempy,temp.step+1,1});
			}
			else
			{
    
    
				q.push_front({
    
    tempx,tempy,temp.step,0});
			}
		}
	}
    return -1;
}
int main(void)
{
    
    
	int t; cin>>t;
	while(t--)
	{
    
    
		cin>>m>>n>>stx>>sty>>edx>>edy>>d;
		swap(stx,sty);
		swap(edx,edy);
		for(int i=1;i<=n;i++)
			for(int j=1;j<=m;j++) cin>>a[i][j];
		cout<<bfs(stx,sty)<<endl;
	}
	return 0;
}

匹配矩阵【模拟】

在这里插入图片描述

#include<bits/stdc++.h> 
using namespace std;
const int N=25;
char a[N][N],b[N][N],c[N][N];
int n1,m1,n2,m2,ans;
void get(int x,int y,int len1,int len2)//判断匹配 
{
    
    
	int flag=1;
	for(int i=0;i<len1;i++)
	{
    
    
		for(int j=0;j<len2;j++)
		{
    
    
			if(b[i][j]=='#') continue;
			if(b[i][j]!=a[i+x][j+y]) flag=0;
		}
	}
	ans+=flag;
}
void solve(int len1,int len2)//枚举左上角的坐标 
{
    
    
	for(int i=0;i<n1;i++)
	{
    
    
		for(int j=0;j<m1;j++)
		{
    
    
			int x=i,xx=i+len1-1;//横 
			int y=j,yy=j+len2-1;//列 
			if(xx>=n1) continue;
			if(yy>=m1) continue;
			get(i,j,len1,len2);
		}
	}
}
void change(int n,int m)
{
    
    
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
			c[j][n-1-i]=b[i][j];
	memcpy(b,c,sizeof c);
}
int main(void)
{
    
    
	int t; cin>>t;
	while(t--)
	{
    
    
		cin>>n1>>m1;
		ans=0;
		for(int i=0;i<n1;i++) 
			for(int j=0;j<m1;j++) cin>>a[i][j];
		cin>>n2>>m2;
		for(int i=0;i<n2;i++)     
			for(int j=0;j<m2;j++) cin>>b[i][j];
		solve(n2,m2);//0
		change(n2,m2),solve(m2,n2);//90
		change(m2,n2),solve(n2,m2);//180
		change(n2,m2),solve(m2,n2);//270
		cout<<ans<<endl;
	}
	return 0;
}

螺旋矩阵【模拟】

在这里插入图片描述
里面到外面旋转和外面到里面旋转一定有某种规律。
找到规律。
在这里插入图片描述
矩阵边长为偶数的话,按照上面的规律重新找。

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
const int M=80;
int st[M][M];
int dx1[4]={
    
    0,-1,0,1};
int dy1[4]={
    
    -1,0,1,0};
int dx2[4]={
    
    0,1,0,-1};
int dy2[4]={
    
    1,0,-1,0};
int main(void)
{
    
    
	int t; cin>>t;
	while(t--)
	{
    
    
		string s; cin>>s;
        memset(st,0,sizeof st);
        int w=s.size();
		for(int i=1;i<=80;i++)
		{
    
    
			if(i*i>=s.size())
			{
    
    
				while(s.size()<i*i) s+=" ";
				break;
			}
		}
		int n=sqrt(s.size());
		s=" "+s; 
		if(n&1)
		{
    
    
			int x=n,y=n,d=0,cnt=0,step=1;
			while(cnt<n*n)
			{
    
    
				st[x][y]=step++;
				cnt++;
				int tempx=x+dx1[d],tempy=y+dy1[d];
				if(tempx>n||tempx<=0||tempy<=0||tempy>n||st[tempx][tempy]) d=(d+1)%4;
				x=x+dx1[d],y=y+dy1[d];
			}
			for(int i=1;i<=n;i++)
			{
    
    
				string temp;
				int flag=0;
				for(int j=1;j<=n;j++)
				{
    
    
					int id=n*n+1-st[i][j];
					temp+=s[id];
					if(s[id]!=' ') flag=1;
				}
				if(flag) cout<<temp<<endl;
			}
		}
        else
		{
    
    
			int x=1,y=1,d=0,cnt=0,step=1;
			while(cnt<n*n)
			{
    
    
				st[x][y]=step++;
				cnt++;
				int tempx=x+dx2[d],tempy=y+dy2[d];
				if(tempx>n||tempx<=0||tempy<=0||tempy>n||st[tempx][tempy]) d=(d+1)%4;
				x=x+dx2[d],y=y+dy2[d];
			}
			for(int i=1;i<=n;i++)
			{
    
    
				string temp;
				int flag=0;
				for(int j=1;j<=n;j++)
				{
    
    
					int id=n*n+1-st[i][j];
					temp+=s[id];
					if(s[id]!=' ') flag=1;
				}
				if(flag) cout<<temp<<endl;
			}
		}
		cout<<endl;
	}
	return 0; 
} 

统计个数【暴力】

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
int g[210][210];
int st[205][205][205]={
    
    0};
struct node{
    
    int a,b,c;};
int gcd(int a,int b)
{
    
    
	return b?gcd(b,a%b):a;
}
int main(void)
{
    
    
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    //如果编译开启了 C++11 或更高版本,建议使用 std::cin.tie(nullptr);
	int t; cin>>t;
	while(t--)
	{
    
    
		int n,m; cin>>n>>m;
		for(int i=1;i<=n;i++)
		{
    
    
			for(int j=1;j<=n;j++)
			{
    
    
				g[i][j]=0;
				for(int k=1;k<=n;k++) 
					st[i][j][k]=0;
			}
		}
		while(m--)
		{
    
    
			int a,b; cin>>a>>b;
			g[a][b]=1,g[b][a]=1;
		}
		int cnt1=0,cnt2=0;
		for(int i=1;i<=n;i++)
		{
    
    
			for(int j=1;j<=n;j++)
			{
    
    
				for(int z=1;z<=n;z++)
				{
    
    
					if(i==j||i==z||j==z) continue;
					if(g[i][j]&&g[j][z])
					{
    
    
						if(st[i][j][z]) continue;
						st[i][j][z]=1,st[z][j][i]=1;
						cnt1++;
						if(g[i][z]) cnt2++;
					}
				}
			}
		}
		if(cnt2==0) cout<<"0/1"<<'\n';
		else
		{
    
    
			 int temp=gcd(cnt2,cnt1);
			 cout<<cnt2/temp<<"/"<<cnt1/temp<<'\n';
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_46527915/article/details/124792055