hdu2510 dfs打表

来源:互联网 发布:石狮淘宝运营培训 编辑:程序博客网 时间:2024/05/22 05:20

符号三角形

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1375    Accepted Submission(s): 731

Problem Description
符号三角形的 第1行有n个由“+”和”-“组成的符号 ,以后每行符号比上行少1个,2个同号下面是”+“,2个异 号下面是”-“ 。计算有多少个不同的符号三角形,使其所含”+“ 和”-“ 的个数相同 。 n=7时的1个符号三角形如下:
+ + - + - + +
+ - - - - +
- + + + -
- + + -
- + -
- -
+
 


Input
每行1个正整数n <=24,n=0退出.
 


Output
n和符号三角形的个数.
 


Sample Input
15 16 19 20 0
 


Sample Output
15 1896
16 5160
19 32757
20 59984
 
这个题并不难, 只要在第一行上dfs就行了, 他下面的那些行可以由第一行得到.
有个剪枝技巧是:
求n时, 有(1+n)/n*2 个符号(等差数列求和), 如果符号数不是偶数的话, 不用算了, 直接就是0.
无奈我写的dfs效率不行, 重复工作太多,时间超了, 但是好像一共就几个数啊, 所以宝宝不要脸地打表AC了.
打表AC代码:
#include <iostream> using namespace std;   int result[24]={0,0,4,6,0,0,12,40,0,0,171,410,0,0,1896,5160,0,0,32757,59984,0,0,431095,822229}; int main() { int n; cin>>n;while(n!=0){cout<<n<<" "<<result[n-1]<<endl;cin>>n;}return 0;}

宝宝写的dfs算法:

#include<cstdio>#include<cstring>#include<iostream>using namespace std;int red[30], n,tot;int mp[30][30];int ans[30];bool check(){    int pluss,minu;    pluss=minu=0;    int sum=(1+n)*n/2;    for(int i=0;i<n;i++){        mp[0][i]=red[i];        if(mp[0][i]=='+')pluss++;        else minu++;        if(pluss>(sum/2))return false;        if(minu>(sum/2))return false;    }    for(int i=1;i<n;i++){        for(int j=0;j<n-i;j++){            mp[i][j]=(mp[i-1][j]==mp[i-1][j+1]?'+':'-');            if(mp[i][j]=='+')pluss++;            else minu++;            if(pluss>(sum/2))return false;            if(minu>(sum/2))return false;//剪枝        }    }    return minu==pluss;}void dfs(int deep){    if(deep>=n){        if(check())tot++;        return;    }    red[deep]='+';    dfs(deep+1);    red[deep]='-';    dfs(deep+1);}int main(){    ans[1]=0;    for(n=2;n<=24;n++){        if(((1+n)*n/2)%2==1){//剪枝            ans[n]=0;            continue;        }        tot=0;        dfs(0);        ans[n]=tot;        printf("%d %d\n",n,ans[n]);    }    while(cin>>n && n){        printf("%d %d\n",n,ans[n]);    }    return 0;}

大神写的

#include<stdio.h>#include<string.h>int ans[30];int a[30][30];//用于保存每个n的第一层的状态的中间过程int count;//记录1的个数void DFS(int n){    int i,j;      if(n>24) return ;      for(i=0;i<=1;i++)      {           a[1][n]=i;//只需要暴力第一行即可           count+=i;               for(j=2;j<=n;j++)               {                   a[j][n-j+1]=a[j-1][n-j+1]^a[j-1][n-j+2];                   count+=a[j][n-j+1];               }               if(count*2==n*(n+1)/2)                  ans[n]++;            DFS(n+1);            count-=i;             for(j=2;j<=n;j++)               {                   a[j][n-j+1]=a[j-1][n-j+1]^a[j-1][n-j+2];                   count-=a[j][n-j+1];               }      }}int main(){    int i,j,k,n;    memset(ans,0,sizeof(ans));    count=0;  DFS(1);  while(scanf("%d",&n)!=EOF)      {          if(!n) break;          printf("%d\n",ans[n]);      }      return 0;}

0 0
原创粉丝点击