MDeath-Kid

- M I T & Y
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

福州大学oj 2030 排列数的枚举

Posted on 2011-05-04 21:01  MDeath-Kid  阅读(579)  评论(0编辑  收藏  举报
/*ACMer:MDK
时间居然是最慢的一个。。。汗。
UserID: MDKSubmit time: 2011-04-30 17:29:16Language: C++Length: 2061 Bytes.Result: Accepted
*/
#include<stdio.h>
#include<iostream>
#include<limits.h>
#include<string.h>
#include<math.h>

#include<vector>
#include<algorithm>
#include<set>
#include<map>
#include<stack>

#define MAXN 2000

using namespace std;
char c[20],a[20];
string ku="0000000000000000000";
void fun(int n,int r){
    if(n){
       fun(n/r,r);
       ku+=n%r>9? n%r-10+'A':n%r+'0';
    }
}
int next(int j)
{
    for(int i = j+1;i<strlen(a);i++)
        if(a[i]!=' ') {
            //cout<<"next(j) :"<<i<<endl;
            return i;
            }
    return MAXN;
}
int OK()
{
    for(int i = 0;i<strlen(a);i++)
    {
        for(int j = 0 ;j<strlen(a);j++)
        {
            if(a[j]=='('&&next(j)!=MAXN&&a[next(j)]==')')
            {
                a[j]=' ';
                a[next(j)]=' ';
            }
        }
    }
    for(int i = 0;i<strlen(a);i++)
        if(a[i]!=' ') return 0;
    return 1;
}
int main()
{
    while(cin>>c)
    {
        int n=0,d[20],flag=0,num=0;
        for(int i = 0;i<strlen(c);i++)
        {
            if(c[i]=='?') d[n]=i,n++;
        }
        if(n==0) cout<<"-0"<<endl;
        else
        {
            for(int i = 0;i<pow(2,n);i++)
            {
                fun(flag++,2);
                strcpy(a,c);
                for(int j = 0;j<n;j++)
                {
                    if(ku[ku.length()-1-j]=='0')
                        a[d[j]]='(';
                    if(ku[ku.length()-1-j]=='1')
                        a[d[j]]=')';
                }
                if(OK())
                {
                    num++;
                }
                ku="000000000000000000";
            }
            cout<<num<<endl;
        }
    }
}

主要思想是枚举,很是笨的方法,丑陋的代码贴着了.

找到了一个把所有排列情况枚举出来的方法,主要原理是用进制的限制。

string ku="0000000000000000000";
void fun(int n,int r){ //10进制对各个进制的转换,代码之精简非常感谢我的朋友LY
if(n){
fun(n
/r,r);
ku
+=n%r>9? n%r-10+'A':n%r+'0';
}
}

这里就是采用了二进制的数,因为只有“(”和“)”两种枚举情况,几种情况就是几进制的。

然后就是hash:

1 fun(flag++,2);
2 strcpy(a,c);
3 for(int j = 0;j<n;j++)
4 {
5 if(ku[ku.length()-1-j]=='0')
6 a[d[j]]='(';
7 if(ku[ku.length()-1-j]=='1')
8 a[d[j]]=')';
9 }

接着就是判断是否满足条件的函数了,easy了。

排列数的枚举。