【洛谷算法1-3】暴力枚举

P2241 统计方形(数据加强版)【数论 / 有意思】

在这里插入图片描述
https://www.luogu.com.cn/problem/P2241

十年OI一场空,不开 long long见祖宗。 记得开long long

首先矩形的个数: 十分的容易理解。矩形的个数减去正方形的个数就是长方形的个数。

下图载自洛谷题解的灬Amiya灬大佬
在这里插入图片描述
那么正方形的个数如何求? 我看了洛谷的题解,可能是我太笨了,实在想不出为啥那样算。
于是自己写了一个比较笨但是十分易懂的方法。
例:
在这里插入图片描述

#include<cstdio>
#include<iostream>
using namespace std;
int nx[5005],mx[5005];
long long int sum;
unsigned long long int sum1;
int main(void)
{
	long long int n,m;cin>>n>>m;
	for(int i=1;i<=n;i++) nx[i]=n-i+1;//初始化每一个边长的个数
	for(int i=1;i<=m;i++) mx[i]=m-i+1;//初始化每一个边长的个数
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(i==j)//说明是正方形
			sum+=nx[i]*mx[j];
		}
	}
	sum1=(n*(n+1)/2)*(m*(m+1)/2)-sum;
	cout<<sum<<" "<<sum1<<endl;
	return 0;
}

P2089 烤鸡

在这里插入图片描述
https://www.luogu.com.cn/problem/P2089

#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
int n;
int a[10];
int b[60005][10];
int ans=0;
void dfs(int index)
{
	if(index==10)
	{
		int sum=0;
		for(int i=0;i<10;i++) sum+=a[i];
		if(sum==n)
		{
			for(int i=0;i<n;i++) b[ans][i]=a[i];//保存状态
			ans++;
		}
		return;
	}
	for(int i=1;i<=3;i++)
	{
		a[index]=i;
		dfs(index+1);
	}
} 
int main(void)
{
	cin>>n;
	if(n>30||n<10)
	{
		cout<<0<<endl;
		return 0;
	}
	dfs(0);	
	cout<<ans<<endl;
	for(int i=0;i<ans;i++)
	{
		for(int j=0;j<10;j++)
			cout<<b[i][j]<<" ";
		cout<<endl;
	}
	return 0;
}

P1618 三连击(升级版)

在这里插入图片描述
https://www.luogu.com.cn/problem/P1618

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int s[9]={1,2,3,4,5,6,7,8,9};
struct node
{
	int x,y,z;
}stu;
vector<node>ve;
int main(void)
{
	int a,b,c; cin>>a>>b>>c;
	do
	{
		stu.x=s[0]*100+s[1]*10+s[2];
		stu.y=s[3]*100+s[4]*10+s[5];
		stu.z=s[6]*100+s[7]*10+s[8];
		if( (stu.x*b==stu.y*a) && (stu.x*c)==(stu.z*a)) ve.push_back(stu);
		
	}while(next_permutation(s,s+9));
	if(!ve.size()) cout<<"No!!!"<<endl;
	else for(int i=0;i<ve.size();i++) cout<<ve[i].x<<" "<<ve[i].y<<" "<<ve[i].z<<endl;
	return 0;
}

P1036 [NOIP2002 普及组] 选数

在这里插入图片描述
https://www.luogu.com.cn/problem/P1036

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=30;
int a[N];
bool b[N];
int n,k;
int ans;
bool judge(int a)
{
	if(a==1) return false;
	if(a==2) return true;
	int temp=sqrt(a);
	for(int i=2;i<=temp;i++)
	{
		if(a%i==0)
			return false;
	}
	return true;
}
void dfs(int start,int sum)
{
	if(sum==k)
	{
		int s=0;
		for(int i=0;i<n;i++)
		{
			if(b[i]) 
			{
				s+=a[i];
			}
		}
		if(judge(s))
			ans++;
		return;
	}
	for(int i=start;i<n;i++)
	{
		if(!b[i])
		{
			b[i]=true;
			dfs(i,sum+1);
			b[i]=false;
		}
	}
}
int main(void)
{
	cin>>n>>k;
	for(int i=0;i<n;i++) cin>>a[i];
	dfs(0,0);
	cout<<ans<<endl;
	return 0;
} 

P1157 组合的输出

在这里插入图片描述
https://www.luogu.com.cn/problem/P1157

#include<cstdio>
#include<iostream>
using namespace std;
int n,r;
bool a[25];
void dfs(int start,int sum)
{
	if(sum==r)
	{
		for(int i=0;i<=n;i++)
		if(a[i]) printf("%3d",i); 
		cout<<endl;
		return;
	}
	for(int i=start;i<=n;i++)
	{
		a[i]=true;
		dfs(i+1,sum+1);
		a[i]=false;
	}
}
int main(void)
{
	cin>>n>>r;
	dfs(1,0);
	return 0;
} 

P1706 全排列问题

在这里插入图片描述
https://www.luogu.com.cn/problem/P1706

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int a[9]={1,2,3,4,5,6,7,8,9};
int main(void)
{
	int n; cin>>n;
	do
	{
		for(int i=0;i<n;i++) printf("%5d",a[i]);
		cout<<endl;
	}while(next_permutation(a,a+n));
	return 0;
} 
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int a[9];
bool b[10];
int n; 
void dfs(int index)
{
	if(index==n)
	{
		for(int i=0;i<n;i++) printf("%5d",a[i]);
		cout<<endl;
		return;
	}
	for(int i=1;i<=n;i++)
	{
		if(!b[i])
		{
			b[i]=true,a[index]=i;
			dfs(index+1);
			b[i]=false;
		}
	}
}
int main(void)
{
	cin>>n;
	dfs(0);
	return 0;
} 

P1088 [NOIP2004 普及组] 火星人

在这里插入图片描述
https://www.luogu.com.cn/problem/P1088
不要被N吓到,关键点在于m,m<=100。所以直接全排列

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int a[100005];
int main(void)
{
	int n,m; cin>>n>>m;
	for(int i=0;i<n;i++) cin>>a[i];
	while(m--) next_permutation(a,a+n);
	for(int i=0;i<n;i++) cout<<a[i]<<" ";
	return 0;
} 

P3392 涂国旗

在这里插入图片描述
https://www.luogu.com.cn/problem/P3392
数据范围很小,直接暴力枚举两个分割线就行了。

#include<cstdio>
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
string str[55];
int ans,sum=1e9;
int main(void)
{
	int n,m; cin>>n>>m;
	for(int i=0;i<n;i++) cin>>str[i];
	for(int i=0;i<n-2;i++)//分割线1
	{
		for(int j=i+1;j<n-1;j++)//分割线2
		{
			ans=0;
			for(int a1=0;a1<=i;a1++)
			{
				for(int a11=0;a11<m;a11++)//白 
				{
					if(str[a1][a11]!='W') ans++;
				}
			}
			for(int a2=i+1;a2<=j;a2++)
			{
				for(int a22=0;a22<m;a22++)//蓝
				{
					if(str[a2][a22]!='B') ans++;
				}
			}
			for(int a3=j+1;a3<n;a3++)
			{
				for(int a33=0;a33<m;a33++)//红
				{
					if(str[a3][a33]!='R') ans++;
				}
			}
			sum=min(ans,sum);
		}
	}
	cout<<sum<<endl;
}

P3654 First Step (ファーストステップ) 【有意思】

在这里插入图片描述
https://www.luogu.com.cn/problem/P3654

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<set>
using namespace std;
int dx[2]={0,1};//向右,或向下走。避免回去重复 
int dy[2]={1,0}; 
string a[205];
bool hush[205][205];
int ans;
int n,m,k;
void dfs(int x,int y)
{
	for(int i=0;i<2;i++)
	{
		int tempx=x+dx[i];
		int tempy=y+dy[i];
		if(tempx>=0&&tempx<n&&tempy>=0&&tempy<m&&a[tempx][tempy]=='.')
		{
			int j;
			int tempx=x;
			int tempy=y;
			for(j=1;j<=(k-1);j++)
			{
				tempx=tempx+dx[i];
				tempy=tempy+dy[i];
				if(tempx<0||tempx>=n||tempy<0||tempy>=m||a[tempx][tempy]!='.')
				break;
			}
			if(j==k) ans++;
		}
	}
}
int main(void)
{
	cin>>n>>m>>k;
	for(int i=0;i<n;i++) cin>>a[i];
	if(k==1) //特殊情况 
	{
		for(int i=0;i<n;i++)
			for(int j=0;j<m;j++)
				if(a[i][j]=='.') ans++;
		cout<<ans<<endl;
		return 0;
	}
	if(n==1&&m==1)
	{
		if(a[0][0]=='.') cout<<1<<endl;
		else cout<<0<<endl;
		return 0;
	}
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
			if(a[i][j]=='.') dfs(i,j);
	cout<<ans<<endl;
	return 0;
} 

P1149 [NOIP2008 提高组] 火柴棒等式 【有意思】

在这里插入图片描述
https://www.luogu.com.cn/problem/P1149

#include<cstdio>
#include<iostream> 
using namespace std;
int a[10]={6,2,5,5,4,5,6,3,7,6};
//         0 1 2 3 4 5 6 7 8 9
int sum[2005];
int ans;
int main(void)
{
	int n; cin>>n;
	sum[0]=6;
	for(int i=1;i<=2000;i++)//计算前2000的数字各自需要的火柴数 
	{
		int temp=i;
		while(temp)
		{
			int t=temp%10;
			sum[i]+=a[t];
			temp/=10;
		}
	}
	for(int i=0;i<=1000;i++)
	{
		for(int j=0;j<=1000;j++)
		{
			int temp=n-sum[i]-sum[j]-4;
			if(sum[i+j]==temp) ans++;
		}
	}
	cout<<ans<<endl;
	return 0;
}

P3799 妖梦拼木棒 【组合数】

在这里插入图片描述
https://www.luogu.com.cn/problem/P3799

题解:部分载自: zhangziyi_xshsnoi

在这里插入图片描述
首先,我们要知道的是,如果要选4根火柴可以组成等边三角形。
那么必须 有两根是一样长的,且作为边长,另外两根的和等于边长,

那么另外两根有两种情况:

  1. 两根是一样长的。
  2. 两根不是一样长的。

代码如下:

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int a[5005];
int start=1e9,endx=-1e9;//记录最小的数,和最大的数
int mod=1e9+7;
long long int ans;
int main(void) 
{
	int n,number; cin>>n;
	for(int i=0;i<n;i++) scanf("%d",&number),a[number]++,start=min(start,number),endx=max(endx,number);
	for(int i=start;i<=endx;i++)
	{
		if(a[i]>=2)//有两根是一样的,作为边长
		{
			for(int j=start;j<=i/2;j++)
			{
				if((i-j)!=j)//另外两条边是不同的。 
				{
					ans+=(long)a[i]*(a[i]-1)/2*a[j]*a[i-j]%mod;
				}
				else//另外两条边是想同的。 
				{
					ans+=(long)a[i]*(a[i]-1)/2*a[j]*(a[j]-1)/2%mod;
				}
			}
			ans=ans%mod;
		}
	}
	cout<<ans<<endl;
	return 0;
}

P2392 kkksc03考前临时抱佛脚

在这里插入图片描述
https://www.luogu.com.cn/problem/P2392

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
int n;
int s[5];
int a[4][25];
int ans=999999999;
int L,R; 
int cnt;
void dfs(int index,int sum)//index当前的个数, sum当前的科目的下标 
{
	 if(index==s[sum])//做完了 
	 {
	 	ans=min(ans,max(L,R));
	 	return;
	 }
	 
	 L+=a[sum][index];//左 
	 dfs(index+1,sum);
	 L-=a[sum][index];
	 
	 R+=a[sum][index];//右 
	 dfs(index+1,sum);
	 R-=a[sum][index];
} 
int main(void)
{
	cin>>s[0]>>s[1]>>s[2]>>s[3];
	for(int i=0;i<4;i++)
	{
		for(int j=0;j<s[i];j++)
		{
			cin>>a[i][j];
		}
	} 
	for(int i=0;i<4;i++)
	{
		ans=999999;//初始化 
		L=R=0;//初始化 
		dfs(0,i);
		cnt+=ans;//总的时间 
	} 
	cout<<cnt<<endl;
	return 0;
}

P2036 [COCI2008-2009#2] PERKET

在这里插入图片描述
https://www.luogu.com.cn/problem/P2036

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
//pair<int,int>p; 
int n;
struct node
{
	int a;
	int b;
}Node[15];
bool m[15];
int ans=999999;
void dfs(int index)
{
	if(index==n)
	{
		int sum1=1;
		int sum2=0;
		for(int i=0;i<n;i++)
		{
			if(m[i])
			{
				sum1*=Node[i].a;
				sum2+=Node[i].b;
			}
		}
		int sum=abs(sum1-sum2);
		if(sum2!=0)
			ans=min(ans,sum);
		return;
	}
	
	m[index]=true;
	dfs(index+1);
	
	m[index]=false;
	dfs(index+1);
}
int main(void)
{
	cin>>n;
	for(int i=0;i<n;i++) cin>>Node[i].a>>Node[i].b;
	dfs(0);
	cout<<ans;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值