• 2017.12.7 算法分析----符号三角型问题(回溯法)


    算法分析:

    符号三角问题:下面都是“-”。 下图是由14个“+”和14个“-”组成的符号三角形。2个同号下面都是“+”,2个异号下面都是“-”。

    在一般情况下,符号三角形的第一行有n个符号。符号三角形问题要求对于给定的n,计算有多少个不同的符号三角形,使其所含的“+”和“-”的个数相同。

    实验提示如下:

    void Triangle::Backtrack(int t)
    
    {
    
      if ((count>half)||(t*(t-1)/2-count>half)) return;
    
      if (t>n) sum++;
    
        else
    
          for (int i=0;i<2;i++) {
    
            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;
    
         }
    
      }
    
    

    解题思路:

    **
    1、不断改变第一行每个符号,搜索符合条件的解,可以使用递归回溯

    为了便于运算,设+ 为0,- 为1,这样可以使用异或运算符表示符号三角形的关系

    ++为+即0^0=0, --为+即1^1=0, +-为-即0^1=1, -+为-即1^0=1;

    2、因为两种符号个数相同,可以对题解树剪枝,

    当所有符号总数为奇数时无解,当某种符号超过总数一半时无解.**

    #include <iostream> 
    using namespace std; 
    class Triangle 
    { 
    	private: 
    		int n;//第一行的符号数量 
    		int **p;//存储+ -号,0表示-,1表示+ 
    		int count;//记录+号数量,根据+号数量,可以用i*(i+1)/2-count求出减号数量 
    		int sum;//记录+与-数量相等且等于num*(num+1)/4的情况 
    		const int half;//加号=等号=总符号数/2 
    		
    	public: 
    	//构造函数 
    		Triangle(int n):half(n*(n+1)/4) { 
    			this->n=n; 
    			count=0; 
    			sum=0; 
    
    			p=new int* [n+1]; 
    			for(int i=0;i<=n;i++) { 
    				p[i]=new int[n+1];//开辟一个num*num的矩阵,用于在回溯过程中记录三角形符号分布 
    	} 
    } 
    
    //调用回溯算法,并且先判断num*(num+1)/2是否为奇数 
    void triangleSolve(); 
    void Backtrack(int t);
    void display();
    };
    void Triangle::Backtrack(int t)
    {
    	if ((count>half)||(t*(t-1)/2-count>half)) return;
    		if (t>n) sum++;
    		else
    			for (int i=0;i<2;i++) {
    			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];//相同则为1,不同则为0,代表题目的规则.1为+,0为- 
    			count+=p[j][t-j+1];
    		}
    		Backtrack(t+1);
    			for (int j=2;j<=t;j++)
    			count-=p[j][t-j+1];
    				count-=i;
    	}
    }
    
    
    void Triangle::triangleSolve() 
    { 
    	if(n*(n+1)/2%2==0) 
    	{ 
    		Backtrack(1); 
    		display(); 
    	}else { 
    		cout<<"不存在可能性"<<endl; 
    		return; 
    	} 
    } 
    void Triangle::display() 
    { 
    	cout<<"边长为"<<n<<"的情况下,一共有"<<sum<<"种符号三角形具有同等数量的+与-号"<<endl; 
    } 
    
    int main() { 
    	int n;
    		cout<<"请输入第一行符号的数量n,[n*(n+1)整除4]:";
    		cin>>n;
    		Triangle test(n);//设置第一行有7个符号 
    		test.triangleSolve();//解决问题 
    			return 0;
    }  
    
  • 相关阅读:
    ohmyzsh
    https://github.com/
    init 0,1,2,3,4,5,6
    关于反射
    docker学习笔记
    docker常见问题汇总
    ArrayList的sublist
    java-锁
    CAS-原子操作
    hashMap与concurrentHashMap
  • 原文地址:https://www.cnblogs.com/qichunlin/p/7999824.html
Copyright © 2020-2023  润新知