zoukankan      html  css  js  c++  java
  • NYOJY 491 幸运三角形

    描述

            话说有这么一个图形,只有两种符号组成(‘+’或者‘-’),图形的最上层有n个符号,往下个数依次减一,形成倒置的金字塔形状,除第一层外(第一层为所有可能情况),每层形状都由上层决定,相邻的符号相同,则下层的符号为‘+’,反之,为‘-’;如下图所示(n = 3 时的两种情况):

                                               

    如果图中的两种符号个数相同,那这个三角形就是幸运三角形,如上图中的图(2).

    输入
    有多组测试数据(少于20组)。
    每行含一个整数n(0<n<20)。
    输出
    输出相应的幸运三角形个数。
    样例输入
    3
    4
    
    样例输出
    4
    6
    ///排列组合第一行,然后直接寻找是否相等
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define N 1010
    #define MOD 1000000007
    using namespace std;
    int n,m,ans[25];
    int a[25];///待排列的数存储在此
    bool vis[15];
    int p[N][N],k;
    int sum,num,tot;
    void dfs(int cnt)///按字典序输出n个数选m个数的所有排列
    {
        if(cnt==m)
        {
            for(int i=0; i<m; i++)
            {
                if(ans[i] == ans[i+1] && i+1 < m)
                    p[1][k] = 1,sum++;
                else
                    p[1][k] = 2;
                k++;
                if(ans[i] == 1)
                    sum++;
            }
            int c = 2;
            while(c < m)
            {
                k = 0;
                for(int i = 0; i < m - c + 1; i++)
                {
                    if(p[c-1][i] == p[c-1][i+1] && i+1 < m - c + 1)
                        p[c][k] = 1,sum++;
                    else
                        p[c][k] = 2;
                    k++;
                }
                c++;
            }
            if(sum == num)
                tot++;
            k = 0;
    //        for(int i=0; i<m; i++)
    //            cout<<ans[i]<<"***";
    //        cout<<endl;
    //        for(int i = 1; i < m; i++)
    //        {
    //            for(int j = 0 ; j < m-i; j++)
    //                cout<<p[i][j]<<"***";
    //            cout<<endl;
    //        }
    //        cout<<sum<<" "<<num<<endl;
            sum = 0;
            return ;
        }
        for(int i=0; i<n; i++)
        {
            ans[cnt]=a[i];
            dfs(cnt+1);
        }
    }
    int main()
    {
        while(cin>>m)
        {
            k = 0;
            n = 2;
            sum = 0;
            tot = 0;
            num = m * (m + 1);
            if(num % 4)
            {
                cout<<0<<endl;
                continue;
            }
            else
                num /= 4;
            fill(vis,vis+25,0);
            a[0] = 1;
            a[1] = 2;
            dfs(0);
            cout<<tot<<endl;
        }
        return 0;
    }
    TLE

    纯粹dfs,回溯还未入门,不过如果应试的话完全可以打表,毕竟数据量不是太大。

    ///排列组合第一行,然后直接寻找是否相等
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define N 1010
    #define MOD 1000000007
    using namespace std;
    int n,m,ans[25];
    int a[25];///待排列的数存储在此
    bool vis[15];
    int p[N][N],k;
    int sum,num,tot;
    void dfs(int cnt)///按字典序输出n个数选m个数的所有排列
    {
        if(cnt==m)
        {
            for(int i=0; i<m; i++)
            {
                if(ans[i] == ans[i+1] && i+1 < m)
                    p[1][k] = 1,sum++;
                else
                    p[1][k] = 2;
                k++;
                if(ans[i] == 1)
                    sum++;
            }
            int c = 2;
            while(c < m)
            {
                k = 0;
                for(int i = 0; i < m - c + 1; i++)
                {
                    if(p[c-1][i] == p[c-1][i+1] && i+1 < m - c + 1)
                        p[c][k] = 1,sum++;
                    else
                        p[c][k] = 2;
                    k++;
                }
                c++;
            }
            if(sum == num)
                tot++;
            k = 0;
    //        for(int i=0; i<m; i++)
    //            cout<<ans[i]<<"***";
    //        cout<<endl;
    //        for(int i = 1; i < m; i++)
    //        {
    //            for(int j = 0 ; j < m-i; j++)
    //                cout<<p[i][j]<<"***";
    //            cout<<endl;
    //        }
    //        cout<<sum<<" "<<num<<endl;
            sum = 0;
            return ;
        }
        for(int i=0; i<n; i++)
        {
            ans[cnt]=a[i];
            dfs(cnt+1);
        }
    }
    int main()
    {
        for(m = 1; m < 21; m++)
            //while(cin>>m)
        {
            k = 0;
            n = 2;
            sum = 0;
            tot = 0;
            num = m * (m + 1);
            if(num % 4)
            {
                cout<<0<<",";
                continue;
            }
            else
                num /= 4;
            fill(vis,vis+25,0);
            a[0] = 1;
            a[1] = 2;
            dfs(0);
            cout<<tot<<",";
        }
        return 0;
    }
    打表过了

    回溯才是正解,可以减掉重复计算的值,但是自己没搞懂,留下正解先

    ///边回溯边计算,避免重复计算
    #include"iostream"
    #include<cstring>
    #include<stdio.h>
    #include<time.h>
    using namespace std;
    typedef unsigned char uchar;
    
    //char cc[2]={'+','-'};    //便于输出
    int n,                     //第一行符号总数
        half,                 //全部符号总数一半
        counter;             //1计数,即  '-' 号计数
        
    char **p;                //符号存储空间    
    long sum;                //符合条件的三角形计数
    
    //t,第一行第 t个符号
    void Backtrace(int t)
    {
        int i, j;
        
        if( t > n )
            sum++;
        else
        {
           for(i=0; i<2; ++i)  //只取  0('+')  或者  1('-')
           {
                p[1][t] = i;   //第一行第 t个符号
                counter += i;        //'-'号统计
                for(j=2; j<=t; ++j)    //当第一行符号 >=2时,可以运算出下面行的某些符号(第一行有几个数就可以相应往下计算几行,每次计算过的就不用重复计算) 
                {
                    p[j][t-j+1] = p[j-1][t-j+1]^p[j-1][t-j+2];//通过异或运算下行符号
                    counter += p[j][t-j+1];                        
                }
                if( (counter <= half) && ( t*(t+1)/2 - counter <= half) )//若符号统计未超过半数,并且另一种符号也未超过半数
                    Backtrace(t+1);            //在第一行增加下一个符号    
                //回溯,判断另一种符号情况
                for(j=2; j<=t; ++j)    
                    counter -= p[j][t-j+1];         
                counter -= i;
           }
        }
    }
    
    int main()
    {  
        while(scanf("%d", &n) != EOF)
        {
            counter = 0;
            sum = 0;
            half = n*(n+1)/2;
            
            if( half%2 == 0 )//总数须为偶数,若为奇数则无解
            {
                half /= 2;
                p = new char *[n+1];
                for(int i=0; i<=n; ++i)
                {
                   p[i] = new char[n+1];
                   memset(p[i], 0, sizeof(char)*(n+1));
                }   
                Backtrace(1);
            }    
            printf("%d
    ", sum);
        }
        return 0;
    }
    回溯正解

    http://www.cnblogs.com/dongsheng/archive/2013/06/16/3138607.html

  • 相关阅读:
    leetcode701. Insert into a Binary Search Tree
    leetcode 958. Check Completeness of a Binary Tree 判断是否是完全二叉树 、222. Count Complete Tree Nodes
    leetcode 110. Balanced Binary Tree
    leetcode 104. Maximum Depth of Binary Tree 111. Minimum Depth of Binary Tree
    二叉树
    leetcode 124. Binary Tree Maximum Path Sum 、543. Diameter of Binary Tree(直径)
    5. Longest Palindromic Substring
    128. Longest Consecutive Sequence
    Mac OS下Android Studio的Java not found问题,androidfound
    安卓 AsyncHttpClient
  • 原文地址:https://www.cnblogs.com/ACMERY/p/5278131.html
Copyright © 2011-2022 走看看