http://codeup.cn/contest.php?cid=100000583
问题C
题目
有一个神奇的口袋,总的容积是40,用这个口袋可以变出一些物品,这些物品的总体积必须是40。John现在有n个想要得到的物品,每个物品的体积分别是a1,a2……an。John可以从这些物品中选择一些,如果选出的物体的总体积是40,那么利用这个神奇的口袋,John就可以得到这些物品。现在的问题是,John有多少种不同的选择物品的方式。
输入
输入的第一行是正整数n (1 <= n <= 20),表示不同的物品的数目。接下来的n行,每行有一个1到40之间的正整数,分别给出a1,a2……an的值。
输出
输出不同的选择物品的方式的数目。
样例输入 Copy
2
12
28
3
21
10
5
样例输出 Copy
1
0
AC代码
#include <iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int n,thing[45],Cout;
void dfs(int sum,int i)
{
if(i==n||sum<=0){
if(sum==0)
Cout++;
return;
}
else if(sum>0){
dfs(sum-thing[i+1],i+1);
dfs(sum,i+1);
}
return;
}
int main()
{
while(scanf("%d",&n)!=EOF){
for(int i=0;i<n;i++)
scanf("%d",&thing[i]);
Cout=0;
dfs(40,-1);
printf("%d\n",Cout);
}
return 0;
}
分析
- 边界条件有其二:
1)已经搜索完所有物品
2)当前选择的物品总容量已达到或者超过40
- 在边界中判断:物品总容量是否正好为40,若是则方式+1,结束递归。
- 一般的递归过程:
每次递归下一件物品的取或者不取的情况
所以从-1~n,n时判断边界
问题D
题目
会下国际象棋的人都很清楚:皇后可以在横、竖、斜线上不限步数地吃掉其他棋子。如何将8个皇后放在棋盘上(有8 * 8个方格),使它们谁也不能被吃掉!这就是著名的八皇后问题。
对于某个满足要求的8皇后的摆放方法,定义一个皇后串a与之对应,即a=b1b2…b8,其中bi为相应摆法中第i行皇后所处的列数。已经知道8皇后问题一共有92组解(即92个不同的皇后串)。
给出一个数b,要求输出第b个串。串的比较是这样的:皇后串x置于皇后串y之前,当且仅当将x视为整数时比y小。
输入
第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,包括一个正整数b(1 <= b <= 92)
输出
输出有n行,每行输出对应一个输入。输出应是一个正整数,是对应于b的皇后串。
样例输入 Copy
3
6
4
25
样例输出 Copy
25713864
17582463
36824175
分析
n皇后问题求解
maxn代表是maxn*maxn的棋盘
用P[maxn+1]存储皇后串,下标1~maxn有意义;用hashtable代表列的使用情况
const int maxn=8;
int n,P[maxn+1],m=0;//P【行】=某一列,这样每行只有一个
long long int str[100];
bool hashtable[maxn+1]={false};//用过的列
皇后的行列存储在该元素的下标及内容中
1----maxn下标代表了1~maxn行各有一个皇后(n个),也保证了不会出现重复行的皇后
bool hashtable,当!hashtable[i]才会暂时使其作为皇后来判断是否有冲突,保证了不会出现重复列的皇后
当确保了不是重复行重复列的情况下,再和之前确定的皇后判断是否不在同一对角线下:
列:pre之前的,step当前的
行:P[pre]之前的,i当前的
abs(pre-step)==abs(P[pre]-i)若相等则在同一对角线下
每次保证了不在同一对角线下
当每一行都放入皇后后,把皇后串的列作为一个八位数字的元素存入str数组中
void dfs(int step)//step行1~8,i列1~8
{
if(step==0)
{
for(int i=1;i<=maxn;i++)
str[m]=str[m]*10+P[i];
m++;
}
else{
for(int i=1;i<=maxn;i++){
if(!hashtable[i]){
bool flag=true;//用来判断与之前的皇后是否冲突
for(int pre=maxn;pre>step;pre--)//之前的皇后
if(abs(pre-step)==abs(P[pre]-i)){//若为对角线则冲突
flag=false;//回溯
break;
}
if(flag){//若不冲突则加入 step行i列的皇后
hashtable[i]=true;
P[step]=i;
dfs(step-1);
hashtable[i]=false;//回溯
}
}
}
}
return;
}
给皇后串数组str排序
按题目要求输出
AC代码
#include <iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
const int maxn=8;
int n,P[maxn+1],m=0;//P【行】=某一列,这样每行只有一个
long long int str[100];
bool hashtable[maxn+1]={false};//用过的列
void dfs(int step)//step行1~8,i列1~8
{
if(step==0)
{
for(int i=1;i<=maxn;i++)
str[m]=str[m]*10+P[i];
m++;
}
else{
for(int i=1;i<=maxn;i++){
if(!hashtable[i]){
bool flag=true;//用来判断与之前的皇后是否冲突
for(int pre=maxn;pre>step;pre--)//之前的皇后
if(abs(pre-step)==abs(P[pre]-i)){//若为对角线则冲突
flag=false;//回溯
break;
}
if(flag){//若不冲突则加入 step行i列的皇后
hashtable[i]=true;
P[step]=i;
dfs(step-1);
hashtable[i]=false;//回溯
}
}
}
}
return;
}
int main()
{
dfs(maxn);
sort(str,str+m);
// for(int i=0;i<m;i++)
// printf("%d %lld\n",i,str[i]);
while(scanf("%d",&n)!=EOF){
while(n--){
scanf("%d",&m);
printf("%lld\n",str[m-1]);
}
}
return 0;
}