基本算法(二)

F - 八皇后

 

会下国际象棋的人都很清楚:皇后可以在横、竖、斜线上不限步数地吃掉其他棋子。如何将8个皇后放在棋盘上(有8 * 8个方格),使它们谁也不能被吃掉!这就是著名的八皇后问题。 
对于某个满足要求的8皇后的摆放方法,定义一个皇后串a与之对应,即a=b 1b 2...b 8,其中b i为相应摆法中第i行皇后所处的列数。已经知道8皇后问题一共有92组解(即92个不同的皇后串)。 
给出一个数b,要求输出第b个串。串的比较是这样的:皇后串x置于皇后串y之前,当且仅当将x视为整数时比y小。 

Input

第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,包括一个正整数b(1 <= b <= 92)

Output

输出有n行,每行输出对应一个输入。输出应是一个正整数,是对应于b的皇后串。

Sample Input

2
1
92

Sample Output

15863724
84136275
#include<bits/stdc++.h>
using namespace std;
int queen[92][8],b[8],num;
void que(int i){
	int k; 
	if(i==8){
		for(int j=0;j<8;j++)
		queen[num][j]=b[j]+1;
		num++;
		return;
	}
	for(int j=0;j<8;j++){
		for(k=0;k<i;k++)
			if(b[k]==j||abs(b[k]-j)==abs(k-i))
			break;
		if(k==i){
			b[k]=j;
			que(i+1);
		}
	}
}
int main(){
	int T;
	num=0;
	scanf("%d",&T);
	que(0);
	while(T--){
		int n;
		scanf("%d",&n);
		for(int i=0;i<8;i++)
		printf("%d",queen[n-1][i]);
		printf("\n");
	}
} 

G - 逆波兰表达式

 

逆波兰表达式是一种把运算符前置的算术表达式,例如普通的表达式2 + 3的逆波兰表示法为+ 2 3。逆波兰表达式的优点是运算符之间不必有优先级关系,也不必用括号改变运算次序,例如(2 + 3) * 4的逆波兰表示法为* + 2 3 4。本题求解逆波兰表达式的值,其中运算符包括+ - * /四个。

Input

输入为一行,其中运算符和运算数之间都用空格分隔,运算数是浮点数。

Output

输出为一行,表达式的值。 
可直接用printf("%f\n", v)输出表达式的值v。

Sample Input

* + 11.0 12.0 + 24.0 35.0

Sample Output

1357.000000

Hint

可使用atof(str)把字符串转换为一个double类型的浮点数。atof定义在math.h中。 
此题可使用函数递归调用的方法求解。

#include<bits/stdc++.h>
#include<stack>
char s[3000];
double work(){
	scanf("%s",s);
	int len=strlen(s);
	if(len==1&&!(s[0]>='0'&&s[0]<='9')){
		switch(s[0]){
			case '+':return work()+work();
			case '-':return work()-work();
			case '*':return work()*work();
			case '/':return work()/work();
		}
	}
	else return atof(s);
}
int main(){
	printf("%f\n",work());
}

H - Placing apples

 

We are going to place M same apples into N same plates.

There could be some empty plates.

How many methods do we have?

When we have 7 applesand 3 plates, the methods, (1, 5, 1) and (5, 1, 1) are the same.

Input

The first line is the number of test cases, t. 0<=t<=20 
The next t lines are test cases containing two numbers, M and N. 1<=M, N<=10.

Output

Output the numbers of method in each test case in one line.

Sample Input

1
7 3

Sample Output

8

//递归

当m=0时,不放就是一种方法

当n=0时,没有一种方法

当n<m时,f(m,n)=f(m,m)

当n>m时,可看作至少有一个有空盘子和没有空盘子情况

f(m,n)=f(m,n-1)+f(m-n,n)

#include<bits/stdc++.h>
using namespace std;
int f(int m,int n){
	if(m==0)
	return 1;
	if(n==0)
	return 0;
	if(m<n)
	return f(m,m);
	return f(m,n-1)+f(m-n,n);
}
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		int n,m;
		scanf("%d%d",&m,&n);
		printf("%d\n",f(m,n));
	}
} 

I - 算24

 

给出4个小于10个正整数,你可以使用加减乘除4种运算以及括号把这4个数连接起来得到一个表达式。现在的问题是,是否存在一种方式使得得到的表达式的结果等于24。 

这里加减乘除以及括号的运算结果和运算的优先级跟我们平常的定义一致(这里的除法定义是实数除法)。 

比如,对于5,5,5,1,我们知道5 * (5 – 1 / 5) = 24,因此可以得到24。又比如,对于1,1,4,2,我们怎么都不能得到24。 

Input

输入数据包括多行,每行给出一组测试数据,包括4个小于10个正整数。最后一组测试数据中包括4个0,表示输入的结束,这组数据不用处理。

Output

对于每一组测试数据,输出一行,如果可以得到24,输出“YES”;否则,输出“NO”。

Sample Input

5 5 5 1
1 1 4 2
0 0 0 0

Sample Output

YES
NO

//递归

可以先算2个数的值,这时还剩三个数,再算接下来的两个数,还剩2个数,再算它等不等于24

#include<bits/stdc++.h>
using namespace std;
#define EPS 1e-6
double a[10];
bool is0(double x){
	if(abs(x)<EPS)
	return true;
	else return false;
}
bool is24(double a[],int n){
	if(n==1){
		if(is0(a[0]-24))
		return true;
		else return false;
	}
	double b[10];
	for(int i=0;i<n;i++){
		for(int j=i+1;j<n;j++){
			int m=0;
			for(int k=0;k<n;k++){
				if(k!=i&&k!=j)
				b[m++]=a[k];
			}
			b[m]=a[i]+a[j];
			if(is24(b,m+1))
			return true;
			b[m]=a[i]-a[j];
			if(is24(b,m+1))
			return true;
			b[m]=a[j]-a[i];
			if(is24(b,m+1))
			return true;
			b[m]=a[i]*a[j];
			if(is24(b,m+1))
			return true;
			if(!is0(a[i])){
				b[m]=a[j]/a[i];
				if(is24(b,m+1))
				return true;
			}
			if(!is0(a[j])){
				b[m]=a[i]/a[j];
				if(is24(b,m+1))
				return true;
			}
		}
	}
	return false;
}
int main(){
	while(1){
		for(int i=0;i<4;i++)
			scanf("%lf",&a[i]);
		if(is0(a[0])&&is0(a[1])&&is0(a[2])&&is0(a[3]))
		break;
		if(is24(a,4))
		printf("YES\n");
		else printf("NO\n");
	}
}

J - 二叉树

 



如上图所示,由正整数1,2,3……组成了一颗二叉树。我们已知这个二叉树的最后一个结点是n。现在的问题是,结点m所在的子树中一共包括多少个结点。 

比如,n = 12,m = 3那么上图中的结点13,14,15以及后面的结点都是不存在的,结点m所在子树中包括的结点有3,6,7,12,因此结点m的所在子树中共有4个结点。 

Input

输入数据包括多行,每行给出一组测试数据,包括两个整数m,n (1 <= m <= n <= 1000000000)。最后一组测试数据中包括两个0,表示输入的结束,这组数据不用处理。

Output

对于每一组测试数据,输出一行,该行包含一个整数,给出结点m所在子树中包括的结点的数目。

Sample Input

3 12
0 0

Sample Output

4
#include<bits/stdc++.h>
using namespace std;
int main(){
	int n,m,i,j,ans;
	while(~scanf("%d%d",&m,&n)&&n&&m){
		ans=0;
		int l=2*m,r=2*m+1;
		while(n>=r){
			ans+=r-l+1;
			l*=2;
			r=2*r+1;
		}
		if(n>=l)
		ans+=n-l+1;
		printf("%d\n",ans+1);
	}
} 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值