符號三角形問題-回溯法


問題描述:

  由14個“+”號和14個“-”號組成的符號三角形。

  2個同號下面是“+”號,2個異號下面是“-”號。

如圖:

  +   +   _   +   _   +   +

      +  _   _   _   _   +

       _   +  +  +  _

        _   +   +  _

         _   +  _

          _  _

             +

在一般情況下,符號三角形第一行有N個符號,該問題要求對於給定n計算有多少種不同的符號三角形。使其所含的+  — 個數相同。

算法設計:

  1 x[i] =1 時,符號三角形的第一行的第i個符號為+

  2 x[i] =0時,表示符號三角形的第一行的第i個符號位-

      共有i(i+1)/2個符號組成的符號三角形。

  3 確定x[i+1]的值后,只要在前面確定的符號三角形的右邊加一條邊就擴展為x[1:i+1]所相應的符號三角形。

  4 最后三角形中包含的“+”“-”的個數都為i(i+1)/4,因此搜索時,個數不能超過...若超直接可以剪去分枝。

  5 當給定的n(n+1)/2為奇數時,也不符合三角形要求。

算法描述:

class Triangle
{
    friend int Compute(int);
private:
    void Backtrack(int t);
    int half,
        count,
        **p
    long sum;
};
void Backtrack(int t)
{
    if((count > half) || (t*(t+1)/2-count>half))
        return;
    if(t>n)
        sum++;
    else
    {
        for(int i=0;i<2;j++)
        {
            p[1][t] = i;
            count+=i;
            for(int j=2;j<=t;j++)
            {
                p[j][t-j+1] = p[j-1][t-j+1]^p[j-1][t-j+2];
                count+=p[j][t-j+1];
            }
            Backtrack(t+1);
            for(int j=2;j<=t;j++)
                count -= p[j][t-j+1];
            count -= i;
        }
    }
}
int Compute(int n)
{
    Triangle X;
    X.n = n;
    X.count = 0;
    X.sum = 0;
    X.half = n*(n+1)/2;
    if(X.half%2 == 1)
        return 0;
    X.half = X.half/2;
    int * * p = new int * [n+1];
    for(int i=0;i<=n;i++)
        p[i] = new int [n+1];
    for(int i=0;i<=n;i++)
        for(int j=0;j<=n;j++)
            p[i][j] = 0;
    X.p = p;
    X.Backtrack(1);
    return X.sum;
}

算法實例:

#include <stdio.h>
#include <conio.h>
#define MAX 100

//global variables
int count=0;//the number of '-'
int sum=0;//the number of the result
int p[MAX][MAX]={0};       //1 is '-'  0 is '+'
int n=0;
int half=0;//half=n*(n+1)/4

void back_triangle(int t);

int main()
{
    printf("Please input n:");    
    scanf("%d",&n);
    half=n*(n+1)/2;
    if(half%2!=0)
    {
        printf("The number that you input is not meaningful for this problem!");    
        getch();
        return 1;
    }
    half/=2;
    back_triangle(1);    
    printf("The result is %d",sum);
    getch();
    return 0;
}

void back_triangle(int t)
{
    if(count>half || t*(t-1)/2-count>half)//because of this,the "count==half" is not necessary
        return ;    
    if(t>n)   //the count==half is not necessary
    {
        sum++;
        for(int temp=1;temp<=n;temp++)
        {
            for(int tp=1;tp<=n;tp++)
            {
                printf("%d ",p[temp][tp]);    
            }    
            printf("\n");
        }
        printf("\n");
    }
    else
    {
        int i;
        for(i=0;i<2;i++)
        {
            p[1][t]=i;
            count+=i;
            int j;
            for(j=2;j<=t;j++)
            {
                p[j][t-j+1]=(p[j-1][t-j+1]^p[j-1][t-j+2]);    
                count+=p[j][t-j+1];
            }

            back_triangle(t+1);

            for(j=2;j<=t;j++)
                count-=p[j][t-j+1];
            count-=i;
        }
    }
}

運行結果:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM