计蒜客—外卖餐厅的展示(简单)

华电北风吹
天津大学认知计算与应用重点实验室
日期:2015/12/5

题目链接:
http://nanti.jisuanke.com/t/434

解题技巧:
动态规划,状态压缩,完美匹配

作为设计师的du熊希望在 N 行 4 列的网格里先行放入若干占 1 行 1 列的正方餐厅广告(障碍物),使得剩下来的空间,可以被占 1 行 2 列或 2 行 1 列的长条餐厅广告完美覆盖。du熊希望让你帮他确定,到底有多少种放置若干正方餐厅广告的方案,使得放置若干正方餐厅广告以后剩下的空间可以被若干 1 行 2 列或 2 行 1 列的长条餐厅广告完美覆盖。
完美覆盖即每个没有放入正方餐厅广告的位置会被长条餐厅广告覆盖恰好一次,且广告不可超出页面边界(如果所有的位置都已放入正方餐厅广告也属于完美覆盖)。
因为方案数会很多,我们希望你输出方案数对 1,000,000,007 取模的结果。
输入格式
输入第一行为一个整数 T (1 ≤ T ≤ 20),表示数据组数。
接下来一共 T 行,每行为一个正整数 N (1 ≤ N ≤ 1018),代表页面的长度。
对于简单版本,1 ≤ n ≤ 6;
对于中等版本,1 ≤ n ≤ 1000;
对于困难版本,1 ≤ n ≤ 1018。
输出格式
一共输出 T 行,每行输出该组数据对应的方案数对 1,000,000,007 取模的结果。

解题思路:
由于n<6,暴力搜索,将所有的可能的障碍物分配模式找出来,然后对每个进行匹配,看是否存在完美匹配。

提交代码:

#include <iostream>
using namespace std;

int func(int n);

int main()
{
    int result;
    int T;
    cin>>T;
    while(T--)
    {
        int n;
        cin>>n;
        cout<<func(n)<<endl;
    }
}

int func(int n)
{
    int result=0;
    switch(n)
    {
        case 1:
            result=5;
            break;
        case 2:
            result=54;
            break;
        case 3:
            result=550;
            break;
        case 4:
            result=5700;
            break;
        case 5:
            result=58830;
            break;
        case 6:
            result=607752;
            break;
        default:
            break;
    }
    return result;
}

解题代码:

#include <vector>
#include <iostream>
using namespace std;

#define N 7

int state[N][16];
int limit[N];

vector<int> NextAllowState(int j)
{
    vector<int> v;
    switch (j)
    {
    case 0:
        v = { 0, 3, 9, 12, 15 };
        break;
    case 1:
        v = { 2, 8, 14 };
        break;
    case 2:
        v = { 1, 13 };
        break;
    case 3:
        v = { 0, 12 };
        break;
    case 4:
        v = { 8, 11 };
        break;
    case 5:
        v = { 10 };
        break;
    case 6:
        v = { 9 };
        break;
    case 7:
        v = { 8 };
        break;
    case 8:
        v = { 1, 4, 7 };
        break;
    case 9:
        v = { 0, 6 };
        break;
    case 10:
        v = { 5 };
        break;
    case 11:
        v = { 4 };
        break;
    case 12:
        v = { 0, 3 };
        break;
    case 13:
        v = { 2 };
        break;
    case 14:
        v = { 1 };
        break;
    case 15:
        v = { 0 };
        break;
    default:
        break;
    }
    return v;
}

bool IsOk(bool * p, int length)
{
    memset(state, 0, sizeof(state));
    int n = length / 4;
    for (int i = 0; i < n; i++)
    {
        limit[i] = 0;
        for (int j = 0; j < 4; j++)
            limit[i] += pow(2, 3 - j)*p[4 * i + j];
    }
    state[0][0] = true;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < 16; j++)
        {
            if ((j&limit[i]) != 0)
                state[i][j] = false;
            if (state[i][j] == true)
            {
                int real_j = j^limit[i];
                vector<int> v = NextAllowState(real_j);
                for (int k = 0; k < v.size(); k++)
                    state[i + 1][v[k]] = true;
            }
        }
    }
    if (state[n][0] == true)
        return true;
    else
        return false;
}

void StateFunc(bool *p, int i, int &length, int &count)
{
    if (i == length)
    {
        count += IsOk(p, length);
        return;
    }
    p[i] = 1;
    StateFunc(p, i + 1, length, count);
    p[i] = 0;
    StateFunc(p, i + 1, length, count);
}

int main()
{
    int n = 5;
    int i = 0, length = 4 * n, count = 0;
    bool * p = new bool[length]();
    StateFunc(p, i, length, count);

    cout <<count << endl;
    getchar();
}

你可能感兴趣的:(计蒜客—外卖餐厅的展示(简单))