遞歸問題


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;
}

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