进阶之路

首页 新随笔 管理

43.  投 n 个骰子,计算点数和出现的概率

递归求解:(空间 O(5*n+1),时间 O(6n))

void count(int N, int curN, int sum, int record[])
{
    if(curN == 0){ ++record[sum - N]; return;}
    for(int i = 1; i <= 6; ++i)
        count(N, curN-1, sum+i, record);
}
void occursNumber(int N, int record[])
{
    if(N < 1) return;
    count(N, N, 0, record);
}

非递归求解:(空间 O(12*n + 2),时间 O(6*n2))

#include <iostream> 
#include <cstring>
using namespace std; 
void occursNumber(unsigned N, unsigned record[])
{
    if(N < 1) return;
    unsigned *tem = new unsigned[6*N +1];
    memset(tem, 0, (6*N+1)*sizeof(unsigned));
    bool flag = 1;
    for(int i = 1; i <= 6; ++i)
        tem[i] = 1;
    
    for(int k = 2; k <= N; ++k)
    {
        if(flag)
        {
            for(int i = 0; i < k; ++i)
                record[i] = 0;
            for(int i = k; i <= 6*k; ++i)
            {
                record[i] = 0;
                for(int j = 1;j <= i && j <= 6; ++j)
                    record[i] += tem[i-j];
            }
        }
        else
        {
            for(int i = 0; i < k; ++i)
                tem[i] = 0;
            for(int i = k; i <= 6*k; ++i)
            {
                tem[i] = 0;
                for(int j = 1; j <= i && j <= 6; ++j)
                    tem[i] += record[i-j];
            }
        }
        flag ^= 1;
    }
    if(N & 1)
    {
        for(int i = N; i <= 6*N; ++i)
            record[i] = tem[i];
    }
    delete[] tem;
}
unsigned long long pow(unsigned exponent)
{
    if(exponent < 1) return 0;
    unsigned long long result = 6;
    unsigned long long tem = 1;
    while(exponent != 1)
    {
        if(exponent & 1) tem *= result;
        result *= result;
        exponent >>= 1;
    }
    result *= tem;
    return result;
}
int main(){ 
    unsigned N, S;
    unsigned long long total;
    cout << "input the number of dice: N " << endl << "cin >> ";
    cin >> N;
    total = pow(N);
    cout << "the total of all number occurs is : " << total << endl;
    cout << "=============================" << endl;
    cout << "input the Sum [N, 6N]" << endl;
    unsigned *record = new unsigned[6*N + 1];
    memset(record, 0, (6*N+1)*sizeof(unsigned));
    occursNumber(N, record);
    while(true)
    {
        cout << "cin >> ";
        cin >> S;
        if(S >= N && S <= 6*N)
            cout << record[S] << endl;
        if(getchar() == 'q') break;
    }
    delete[] record;
    
    return 0; 
} 

shot

44. 取 k 张扑克牌,看其是否是顺子。

大小王用 0 表示,可以看成任意数字。

bool isContinuous(int data[], int length)
{
    if(data == NULL || length < 1) return false;

    qsort(data, length, sizeof(int), cmp);
    int i;
    int num0 = 0, numGap = 0;
    for(i = 0; data[i] == 0 && i < length; ++i)
        ++num0;
    for(; i < length-1; ++i)
    {
        if(data[i] == data[i+1]) return false;
        numGap += data[i+1] - data[i] - 1;
    }
    return (numGap <= num0 ? true : false);
}
int cmp(const void *arg1, const void* arg2)
{
    return *((int*)arg1) > *((int*)arg2);
}

45. 圆圈中最后剩下的数字。

GO:约瑟夫问题

shot

posted on 2014-05-04 16:42  进阶之路  阅读(252)  评论(0编辑  收藏  举报