递归问题


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. 边界条件有其二:

1)已经搜索完所有物品
2)当前选择的物品总容量已达到或者超过40

  1. 在边界中判断:物品总容量是否正好为40,若是则方式+1,结束递归。
  2. 一般的递归过程:
    每次递归下一件物品的取或者不取的情况
    所以从-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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章