Logic 计算矩形的平铺数

Logic 计算矩形的平铺数,logic,game-physics,puzzle,Logic,Game Physics,Puzzle,我试图解决这个问题,但找不到解决方案: class Program { // Important note: // The value of masks given here is hard-coded for m == 5. // In a complete solution, you need to calculate the masks for the // actual value of m given. See explanation in answer

我试图解决这个问题,但找不到解决方案:

class Program
{
    // Important note:
    // The value of masks given here is hard-coded for m == 5.
    // In a complete solution, you need to calculate the masks for the
    // actual value of m given. See explanation in answer for more details.

    int[] masks = { 0, 3, 6, 12, 15, 24, 27, 30 };

    int CountTilings(int n, int m, int s = 0)
    {
        if (n == 1) { return 1; }

        int result = 0;
        foreach (int mask in masks)
        {
            if ((mask & s) == 0)
            {
                result += CountTilings(n - 1, m, mask);
            }
        }
        return result;
    }

    public static void Main()
    {
        Program p = new Program();
        int result = p.CountTilings(6, 5);
        Console.WriteLine(result);
    }
}
// time used : 27 min
#include <set>
#include <vector>
#include <iostream>
using namespace std;
void placement(int n, set< vector <int> > & p){
    for (int i = 0; i < n -1 ; i ++){
        for (set<vector<int> > :: iterator j  = p.begin(); j != p.end(); j ++){
            vector <int> temp = *j;
            if (temp[i] == 1 || temp[i+1] == 1) continue;
            temp[i] = 1; temp[i+1] = 1;
            p.insert(temp);
        }
    }
}

vector<vector<int> > placement( int n){
    if (n > 7) throw "error";
    set <vector <int> > p;
    vector <int> temp (n,0);
    p.insert (temp);
    for (int i = 0; i < 3; i ++) placement(n, p);
    vector <vector <int> > s;
    s.assign (p.begin(), p.end());
    return s;
}


bool tryput(vector <vector <int> > &board, int current, vector<int> & comb){
    for (int i = 0; i < comb.size(); i ++){
        if ((board[current][i] == 1 || board[current+1][i]) && comb[i] == 1) return false;
    }
    return true;
}
void  put(vector <vector <int> > &board, int current, vector<int> & comb){
    for (int i = 0; i < comb.size(); i ++){
        if (comb[i] == 1){
            board[current][i] = 1;
            board[current+1][i] = 1;
        }
    }
    return;
}

void  undo(vector <vector <int> > &board, int current, vector<int> & comb){
    for (int i = 0; i < comb.size(); i ++){
        if (comb[i] == 1){
            board[current][i] = 0;
            board[current+1][i] = 0;
        }
    }
    return;
}



int place (vector <vector <int> > &board, int current,  vector < vector <int> >  & all_comb){
    int m = board.size();
    if (current >= m) throw "error";
    if (current == m - 1) return 1;
    int count = 0;
    for (int i = 0; i < all_comb.size(); i ++){
        if (tryput(board, current, all_comb[i])){
            put(board, current, all_comb[i]);
            count += place(board, current+1, all_comb) % 10000007;
            undo(board, current, all_comb[i]);
        }
    }
    return count;
}
int place (int m, int n){
    if (m == 0) return 0;
    if (m == 1) return 1;
    vector < vector <int> > all_comb = placement(n);
    vector <vector <int> > board(m, vector<int>(n, 0));
    return place (board, 0, all_comb);

}
int main(){
    cout << place(3, 4) << endl;
    return 0;
}
给出了一种由N行M列正方形组成的电路板。这块板的瓷砖是覆盖在上面的瓷砖图案。如果:

    only tiles of size 1x1 and/or 2x2 are used;
    each tile of size 1x1 covers exactly one whole square;
    each tile of size 2x2 covers exactly four whole squares;
    each square of the board is covered by exactly one tile.
例如,以下图像显示了大小为4行3列的电路板的一些有趣的平铺:

如果电路板上至少有一个正方形在一块瓷砖中覆盖着1x1大小的瓷砖,而在另一块瓷砖中覆盖着2x2大小的瓷砖,则电路板上两个有趣的瓷砖是不同的。例如,上面图像中显示的所有平铺都是不同的

写一个函数

int count_tilings(int N, int M); 
给定两个整数N和M,返回大小为N行和M列的电路板上不同有趣的平铺数的10000007模余数

假设:

    N is an integer within the range [1..1,000,000];
    M is an integer within the range [1..7].
例如,给定N=4和M=3,函数应该返回11,因为有11个大小为4行3列的板的不同有趣的平铺:

对于(4,3),结果是11,对于(6,5),结果是1213。 我尝试了以下方法,但无效:

static public int count_tilings(int N,int M){
int结果=1;
如果((N==1)| |(M==1))返回1;
结果=结果+(N-1)*(M-1);
int max_tiling=(int)((int)(Math.ceil(N/2))*(Math.ceil(M/2));
系统输出打印LN(最大平铺);
对于(int i=2;i=2*i){
int n=i+(n-i);
int k=i;
//System.out.println(“M-1->”+(M-1)+“i->”+i);
System.out.println(“(M-1)^i)->”+(Math.pow((M-1),i));
System.out.println(“n=“+n+”k=“+k”);
系统输出println(组合(n,k));
如果(N-i*2>0){
结果+=数学功率((M-1),i)*组合(n,k);
}否则{
结果+=数学功率((M-1),i);
}
}
如果(M>=2*i){
int n=i+(M-i);
int k=i;
System.out.println(“(N-1)^i)->”+(Math.pow((N-1),i));
System.out.println(“n=“+n+”k=“+k”);
系统输出println(组合(n,k));
如果(M-i*2>0){
结果+=数学功率((N-1),i)*组合(N,k);
}否则{
结果+=数学功率((N-1),i);
}
}
}
返回结果;
}
静态长组合(int n,int k){
/*二项式系数*/
长系数=1;

对于(inti=n-k+1;i由于这是家庭作业,我不会给出完整的解决方案,但我会给你一些提示

首先,这里有一个递归解决方案:

class Program
{
    // Important note:
    // The value of masks given here is hard-coded for m == 5.
    // In a complete solution, you need to calculate the masks for the
    // actual value of m given. See explanation in answer for more details.

    int[] masks = { 0, 3, 6, 12, 15, 24, 27, 30 };

    int CountTilings(int n, int m, int s = 0)
    {
        if (n == 1) { return 1; }

        int result = 0;
        foreach (int mask in masks)
        {
            if ((mask & s) == 0)
            {
                result += CountTilings(n - 1, m, mask);
            }
        }
        return result;
    }

    public static void Main()
    {
        Program p = new Program();
        int result = p.CountTilings(6, 5);
        Console.WriteLine(result);
    }
}
// time used : 27 min
#include <set>
#include <vector>
#include <iostream>
using namespace std;
void placement(int n, set< vector <int> > & p){
    for (int i = 0; i < n -1 ; i ++){
        for (set<vector<int> > :: iterator j  = p.begin(); j != p.end(); j ++){
            vector <int> temp = *j;
            if (temp[i] == 1 || temp[i+1] == 1) continue;
            temp[i] = 1; temp[i+1] = 1;
            p.insert(temp);
        }
    }
}

vector<vector<int> > placement( int n){
    if (n > 7) throw "error";
    set <vector <int> > p;
    vector <int> temp (n,0);
    p.insert (temp);
    for (int i = 0; i < 3; i ++) placement(n, p);
    vector <vector <int> > s;
    s.assign (p.begin(), p.end());
    return s;
}


bool tryput(vector <vector <int> > &board, int current, vector<int> & comb){
    for (int i = 0; i < comb.size(); i ++){
        if ((board[current][i] == 1 || board[current+1][i]) && comb[i] == 1) return false;
    }
    return true;
}
void  put(vector <vector <int> > &board, int current, vector<int> & comb){
    for (int i = 0; i < comb.size(); i ++){
        if (comb[i] == 1){
            board[current][i] = 1;
            board[current+1][i] = 1;
        }
    }
    return;
}

void  undo(vector <vector <int> > &board, int current, vector<int> & comb){
    for (int i = 0; i < comb.size(); i ++){
        if (comb[i] == 1){
            board[current][i] = 0;
            board[current+1][i] = 0;
        }
    }
    return;
}



int place (vector <vector <int> > &board, int current,  vector < vector <int> >  & all_comb){
    int m = board.size();
    if (current >= m) throw "error";
    if (current == m - 1) return 1;
    int count = 0;
    for (int i = 0; i < all_comb.size(); i ++){
        if (tryput(board, current, all_comb[i])){
            put(board, current, all_comb[i]);
            count += place(board, current+1, all_comb) % 10000007;
            undo(board, current, all_comb[i]);
        }
    }
    return count;
}
int place (int m, int n){
    if (m == 0) return 0;
    if (m == 1) return 1;
    vector < vector <int> > all_comb = placement(n);
    vector <vector <int> > board(m, vector<int>(n, 0));
    return place (board, 0, all_comb);

}
int main(){
    cout << place(3, 4) << endl;
    return 0;
}
在线查看它的工作情况:

请注意,我添加了一个额外的参数
s
。这将存储第一列的内容。如果第一列为空,s=0。如果第一列包含一些填充的正方形,则设置s中的相应位。最初s=0,但当放置一个2 x 2平铺时,这将填充下一列中的一些正方形,这意味着在递归调用中,s将不为零

masks
变量是硬编码的,但在完整的解决方案中,它需要根据
m
的实际值进行计算。
masks
中存储的值在查看其二进制表示形式时更有意义:

00000
00011
00110
01100
01111
11000
11011
11110
换句话说,它是用m位设置二进制数中的位对的所有方法。您可以编写一些代码来生成所有这些可能性。或者,由于m只有7个可能值,您也可以硬编码
掩码的所有7个可能值


然而,递归解决方案有两个严重的问题

  • 如果
    N
    的值较大,则会使堆栈溢出
  • 计算需要指数时间。即使是
    N
  • 这两个问题都可以通过重写要迭代的算法来解决。保持
    m
    恒定,并初始化
    n=1
    的结果,使
    s
    的所有可能值都成为
    1
    。这是因为如果只有一列,则必须只使用1x1分幅,并且只有一种方法可以做到这一点


    现在,您可以使用
    n=1
    的结果来计算
    n=2
    所有可能的
    s
    值。这可以重复,直到您达到
    n=n
    。此算法在与
    n
    相关的线性时间内完成,并且需要恒定的空间。

    这里是一个递归解决方案:

    class Program
    {
        // Important note:
        // The value of masks given here is hard-coded for m == 5.
        // In a complete solution, you need to calculate the masks for the
        // actual value of m given. See explanation in answer for more details.
    
        int[] masks = { 0, 3, 6, 12, 15, 24, 27, 30 };
    
        int CountTilings(int n, int m, int s = 0)
        {
            if (n == 1) { return 1; }
    
            int result = 0;
            foreach (int mask in masks)
            {
                if ((mask & s) == 0)
                {
                    result += CountTilings(n - 1, m, mask);
                }
            }
            return result;
        }
    
        public static void Main()
        {
            Program p = new Program();
            int result = p.CountTilings(6, 5);
            Console.WriteLine(result);
        }
    }
    
    // time used : 27 min
    #include <set>
    #include <vector>
    #include <iostream>
    using namespace std;
    void placement(int n, set< vector <int> > & p){
        for (int i = 0; i < n -1 ; i ++){
            for (set<vector<int> > :: iterator j  = p.begin(); j != p.end(); j ++){
                vector <int> temp = *j;
                if (temp[i] == 1 || temp[i+1] == 1) continue;
                temp[i] = 1; temp[i+1] = 1;
                p.insert(temp);
            }
        }
    }
    
    vector<vector<int> > placement( int n){
        if (n > 7) throw "error";
        set <vector <int> > p;
        vector <int> temp (n,0);
        p.insert (temp);
        for (int i = 0; i < 3; i ++) placement(n, p);
        vector <vector <int> > s;
        s.assign (p.begin(), p.end());
        return s;
    }
    
    
    bool tryput(vector <vector <int> > &board, int current, vector<int> & comb){
        for (int i = 0; i < comb.size(); i ++){
            if ((board[current][i] == 1 || board[current+1][i]) && comb[i] == 1) return false;
        }
        return true;
    }
    void  put(vector <vector <int> > &board, int current, vector<int> & comb){
        for (int i = 0; i < comb.size(); i ++){
            if (comb[i] == 1){
                board[current][i] = 1;
                board[current+1][i] = 1;
            }
        }
        return;
    }
    
    void  undo(vector <vector <int> > &board, int current, vector<int> & comb){
        for (int i = 0; i < comb.size(); i ++){
            if (comb[i] == 1){
                board[current][i] = 0;
                board[current+1][i] = 0;
            }
        }
        return;
    }
    
    
    
    int place (vector <vector <int> > &board, int current,  vector < vector <int> >  & all_comb){
        int m = board.size();
        if (current >= m) throw "error";
        if (current == m - 1) return 1;
        int count = 0;
        for (int i = 0; i < all_comb.size(); i ++){
            if (tryput(board, current, all_comb[i])){
                put(board, current, all_comb[i]);
                count += place(board, current+1, all_comb) % 10000007;
                undo(board, current, all_comb[i]);
            }
        }
        return count;
    }
    int place (int m, int n){
        if (m == 0) return 0;
        if (m == 1) return 1;
        vector < vector <int> > all_comb = placement(n);
        vector <vector <int> > board(m, vector<int>(n, 0));
        return place (board, 0, all_comb);
    
    }
    int main(){
        cout << place(3, 4) << endl;
        return 0;
    }
    
    //使用时间:27分钟
    #包括
    #包括
    #包括
    使用名称空间std;
    无效位置(int n,set&p){
    对于(int i=0;i7)抛出“错误”;
    设p;
    向量温度(n,0);
    p、 插入(温度);
    对于(inti=0;i<3;i++)位置(n,p);
    向量s;
    s、 赋值(p.begin(),p.end());
    返回s;
    }
    bool tryput(矢量和线路板、整数电流、矢量和梳状){
    对于(int i=0;i&所有梳状){
    int m=board.size();
    如果(当前>=m)抛出“错误”;
    如果(当前==m-1)返回1;
    整数计数=0;
    对于(int i=0;i