pku 1850 Code 组合数学排列组合的应用

http://poj.org/problem?id=1850

以前接触组合数学的东西比较少,以后要训练一些这类的题目了。。http://baike.baidu.com/view/738955.htm

利用的是公式是c[i][j] = c[i - 1][j - 1] + c[i][j - 1] 类比到杨辉三角。这道题目就是给字符串标号,给定的字符串要求满足s[i] < s[i + 1] < s[i + 2] ......,如果不满足则输出0,然后是给定一个字符串输出其编号。我们只要求出所有比他小的字符串的个数茫然后加上他本身就得到了他的编号。假设字符串为s,长度为len

分两部分求:1:首先求长度为1,2,3,......len -1的所有字符串的个数,因为所有的这些字符串肯定小于长度为len 的字符串;2:再从高位到低位锁定最高位,求出锁定最高位后后面所有的个数。

View Code
#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 27
using namespace std;

int c[maxn][maxn];
char s[13];

//求组合数
void init()
{
    int i,j;
    for (i = 0; i <= 26; ++i)
    {
        c[i][0] = 1; c[i][i] = 1;
    }
    for (i = 2; i <= 26; ++i)
    {
        for (j = 1; j <= i - 1; ++j)
        {
            c[i][j] = c[i - 1][j - 1] + c[i - 1][j];
        }
    }
}
//判断是否可编码
bool isok(char *st)
{
    int i,j;
    int len = strlen(st);
    for (i = 0; i < len; ++i)
    {
        for (j = i + 1; j < len; ++j)
        {
            if (st[i] >= st[j]) return false;
        }
    }
    return true;
}
int main()
{
    int ans = 0;
    int i;
    init();
    scanf("%s",s);
    if (!isok(s))
    {
        printf("0\n");
    }
    else
    {
        int len = strlen(s);
        //求长度为1,2,,,,len - 1
        for (i = 1; i < len; ++i)
        {
            ans += c[26][i];
        }
        //因为对于锁定s[0]后,它后面一位的取值是从a - s[0]所以要拿出来单独考虑
        for (char ch = 'a'; ch != s[0]; ch++)
        {
            ans += c['z' - ch][len - 1];
        }
        for (i = 1; i < len; ++i)
        {
            //其余的就是从他的前一个字符开始了
            for (char ch = s[i - 1] + 1; ch != s[i]; ch++)
            {
                ans += c['z' - ch][len - i - 1];
            }
        }
        printf("%d\n",ans + 1);
    }
    return 0;
}
posted @ 2012-05-01 11:17  E_star  阅读(298)  评论(0编辑  收藏  举报