列表

详情


NC17708. Maze

描述

Niuniu likes his maze (Mei Zi) and he wants to collect more mazes.

Given n, m, a maze is a n x m grid. The rows and columns are numbered from 0.
Let's call the cell on the i-th row and the j-th column as (i,j).
There may be vertical walls between (i, j) and (i, j + 1).
There may be horizontal walls between (i, j) and (i + 1, j).

Two array v and h are given.
The size of v is n x (m - 1).
If v[i][j] is 1, then there is a wall between (i, j) and (i, j + 1).
If v[i][j] is 0, then there are two possibilities. There may or may not be a wall between (i, j) and (i, j + 1).

The size of h is (n-1) x m.
If h[i][j] is 1, then there is a wall between (i, j) and (i + 1, j).
If h[i][j] is 0, then there are two possibilities. There may or may not be a wall between (i, j) and (i + 1, j).

The beauty is defined as follows:
Calculate the size of each connected component, the sum of their square is the beauty.

You need output the sum of beauty of all possibilities.
(Obviously, the number of possibilities are 2^{the number of 0 in v and h})

As the answer might be very large, you only need to output the answer mod 1000000007.

输入描述

The first line contains two integer n, m.
In following n lines, each line contains m-1 integers, which are the array v.
In following n-1 lines, each line contains m integers, which are the array h.

1 <= n <= 7
1 <= m <= 7
0 <= v[i][j] <= 1
0 <= h[i][j] <= 1

输出描述

You should output the anwer in one line.

示例1

输入:

2 2
0
0
0 0

输出:

164

说明:

If there is 0 or 1 wall, the beauty is 4 * 4 = 16
If there are 2 walls and they form shape L, the beauty is 3 * 3 + 1 * 1 = 10
If there are 2 walls and they form shape I, the beauty is 2 * 2 + 2 * 2 = 8
If there are 3 walls, the beauty is 2 * 2 + 1 * 1 + 1 * 1 = 6
If there are 4 walls, the beauty is 1 * 1 + 1 * 1 + 1 * 1 + 1 * 1 = 4
The answer should be 16 * 5 + 10 * 4 + 8 * 2 + 6 * 4 + 4 * 1 = 164

示例2

输入:

2 2
0
1
0 1

输出:

26

说明:

The two existing wall forms shape L.
If there is no more wall, the beauty is 3 * 3 + 1 * 1 = 10
If there is 1 more wall, the beauty is 2 * 2 + 1 * 1 + 1 * 1 = 6
If there is 2 more walls, the beauty is 1 * 1 + 1 * 1 + 1 * 1 + 1 * 1 = 4
The answer should be 10 * 1 + 6 * 2 + 4 * 1 = 26

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 218ms, 内存消耗: 87784K, 提交时间: 2018-09-11 19:45:59

#include <iostream>
#include <ios>
#include <cstdint>
#include <vector>

using ul = std::uint32_t;
using ull = std::uint64_t;
using li = std::int32_t;
using ll = std::int64_t;
using vul = std::vector<ul>;
using vvul = std::vector<vul>;
using vvvul = std::vector<vvul>;

const ul base = 1e9 + 7;
const li basel = base;

ul plus(ul a, ul b)
{
    return a + b < base ? a + b : a + b - base;
}

ul minus(ul a, ul b)
{
    return a < b ? a + base - b : a - b;
}

ul times(ul a, ul b)
{
    return ull(a) * b % base;
}

void exgcd(li a, li b, li& x, li& y)
{
    if (b) {
        exgcd(b, a % b, y, x);
        y -= x * (a / b);
    } else {
        x = 1;
        y = 0;
    }
}

ul inverse(ul a)
{
    li x, y;
    exgcd(base, a, x, y);
    return y < 0 ? y + basel : y;
}

vvvul prevans(1 << 16, vvul(9, vul(9, 0)));
vvvul currans(1 << 16, vvul(9, vul(9, 0)));
vul legalcuts;
vvul h(8, vul(8, 1));
vvul v(8, vul(8, 1));
ul n, m;
vul parts;
vul belongpart(9, 0);
vul nexbelongpart(9, 0);

std::ostream& print(std::ostream& os, ul cut) {
    for (ul i = 0; i <= m; ++i) {
        if (i) {
            std::cout << "口";
        }
        if (cut >> i >> i & 1) {
            std::cout << ')';
        }
        if (cut >> i >> i & 2) {
            std::cout << '(';
        }
    }
    return os;
}

int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cin >> n >> m;
    for (ul i = 1; i <= n; ++i) {
        for (ul j = 1; j != m; ++j) {
            std::cin >> v[i][j];
        }
    }
    for (ul i = 1; i != n; ++i) {
        for (ul j = 1; j <= m; ++j) {
            std::cin >> h[i][j];
        }
    }
    for (ul cut = 0; cut != (1 << m << m << 2); ++cut) {
        if ((cut & 3) != 2 || (cut >> m >> m & 3) != 1) {
            continue;
        }
        bool flag = true;
        parts.resize(0);
        for (ul k = 0; k <= m; ++k) {
            ul temp2 = cut >> k >> k & 3;
            if (temp2 & 1) {
                if (parts.empty()) {
                    flag = false;
                    break;
                }
                parts.pop_back();
            }
            if (temp2 & 2) {
                parts.push_back(k + 1);
            }
            if (parts.empty() && k != m) {
                flag = false;
                break;
            }
            belongpart[k + 1] = parts.back();
        }
        if (parts.size()) {
            flag = false;
        }
        if (!flag) {
            continue;
        }
        legalcuts.push_back(cut);
    }
    prevans[(1 << m << m << 1) - 2][0][0] = 1;
    for (ul i = 1; i <= n; ++i) {
        for (ul j = 1; j <= m; ++j) {
            for (ul cut : legalcuts) {
                for (ul a = 0; a <= m + 1; ++a) {
                    for (ul b = 0; b <= m + 1; ++b) {
                        currans[cut][a][b] = 0;
                    }
                }
            }
            for (ul cut : legalcuts) {
                parts.resize(0);
                for (ul k = 0; k <= m; ++k) {
                    ul temp2 = cut >> k >> k & 3;
                    if (temp2 & 1) {
                        parts.pop_back();
                    }
                    if (temp2 & 2) {
                        parts.push_back(k + 1);
                    }
                    belongpart[k + 1] = parts.back();
                }
                ul jto;
                if (belongpart[j] == j) {
                    for (jto = j + 1; jto <= m && belongpart[jto] != j; ++jto) {
                    }
                }
                for (bool up : {false, true}) {
                    if (up < h[i - 1][j]) {
                        continue;
                    }
                    for (bool left : {false, true}) {
                        if (left < v[i][j - 1]) {
                            continue;
                        }
                        ul nexcut = cut;
                        if (up) {
                            ul temp = j - 1;
                            nexcut |= 2 << temp << temp | 1 << temp << temp << 2;
                            if ((~cut >> temp >> temp & 2) && (cut >> temp >> temp >> 2 & 1)) {
                                ul temp2 = 1;
                                ul k;
                                for (k = temp; ; --k) {
                                    if (nexcut >> k >> k & 2) {
                                        --temp2;
                                    }
                                    if (~nexcut >> k >> k & 1) {
                                        if (!temp2) {
                                            break;
                                        }
                                    }
                                    if (nexcut >> k >> k & 1) {
                                        ++temp2;
                                    }
                                }
                                nexcut |= 1 << k << k;
                            } else if ((cut >> temp >> temp & 2) && (~cut >> temp >> temp >> 2 & 1)) {
                                ul temp2 = 1;
                                ul k;
                                for (k = temp + 1; ; ++k) {
                                    if (nexcut >> k >> k & 1) {
                                        --temp2;
                                    }
                                    if (~nexcut >> k >> k & 2) {
                                        if (!temp2) {
                                            break;
                                        }
                                    }
                                    if (nexcut >> k >> k & 2) {
                                        ++temp2;
                                    }
                                }
                                nexcut |= 2 << k << k;
                            }
                        }
                        ul nexnexcut = nexcut;
                        if (!left) {
                            ul temp = j - 1;
                            nexnexcut &= ~(3 << temp << temp);
                            if ((~nexcut >> temp >> temp & 2) && (nexcut >> temp >> temp & 1)) {
                                ul temp2 = 0;
                                ul k;
                                for (k = temp - 1; ; --k) {
                                    if (nexnexcut >> k >> k & 2) {
                                        if (!temp2) {
                                            break;
                                        }
                                        --temp2;
                                    }
                                    if (nexnexcut >> k >> k & 1) {
                                        ++temp2;
                                    }
                                }
                                nexnexcut &= ~(2 << k << k);
                            } else if ((nexcut >> temp >> temp & 2) && (~nexcut >> temp >> temp & 1)) {
                                ul temp2 = 0;
                                ul k;
                                for (k = temp + 1; ; ++k) {
                                    if (nexnexcut >> k >> k & 1) {
                                        if (!temp2) {
                                            break;
                                        }
                                        --temp2;
                                    }
                                    if (nexnexcut >> k >> k & 2) {
                                        ++temp2;
                                    }
                                }
                                nexnexcut &= ~(1 << k << k);
                            }
                        }
                        ul nex = nexnexcut;
                        //print(print(std::cout << i << ' ' << j << ' ', cut) << ' ' << up << ' ' << left << ' ', nex) << std::endl;
                        parts.resize(0);
                        for (ul k = 0; k <= m; ++k) {
                            ul temp2 = nex >> k >> k & 3;
                            if (temp2 & 1) {
                                parts.pop_back();
                            }
                            if (temp2 & 2) {
                                parts.push_back(k + 1);
                            }
                            nexbelongpart[k + 1] = parts.back();
                        }
                        for (ul a = 0; a <= m + 1; ++a) {
                            if (a != 0 && a != m + 1 && belongpart[a] != a) {
                                continue;
                            }
                            for (ul b = 0; b <= m + 1; ++b) {
                                if (b != 0 && b != m + 1 && belongpart[b] != b) {
                                    continue;
                                }
                                if ((a == m + 1) != (b == m + 1)) {
                                    continue;
                                }
                                if (a == m + 1 && b == m + 1) {
                                    currans[nex][a][b] = plus(currans[nex][a][b], prevans[cut][a][b]);
                                } else if (!a && !b) {
                                    currans[nex][nexbelongpart[j]][nexbelongpart[j]] = plus(currans[nex][nexbelongpart[j]][nexbelongpart[j]], prevans[cut][a][b]);
                                    currans[nex][0][nexbelongpart[j]] = plus(currans[nex][0][nexbelongpart[j]], prevans[cut][a][b]);
                                    currans[nex][nexbelongpart[j]][0] = plus(currans[nex][nexbelongpart[j]][0], prevans[cut][a][b]);
                                    currans[nex][0][0] = plus(currans[nex][0][0], prevans[cut][a][b]);
                                } else if (a && !b) {
                                    if (a != j) {
                                        currans[nex][nexbelongpart[a]][nexbelongpart[j]] = plus(currans[nex][nexbelongpart[a]][nexbelongpart[j]], prevans[cut][a][b]);
                                        currans[nex][nexbelongpart[a]][0] = plus(currans[nex][nexbelongpart[a]][0], prevans[cut][a][b]);
                                    } else {
                                        if (up) {
                                            if (jto > m) {
                                                continue;
                                            }
                                            currans[nex][jto][nexbelongpart[j]] = plus(currans[nex][jto][nexbelongpart[j]], prevans[cut][a][b]);
                                            currans[nex][jto][0] = plus(currans[nex][jto][0], prevans[cut][a][b]);
                                        } else {
                                            currans[nex][nexbelongpart[j]][nexbelongpart[j]] = plus(currans[nex][nexbelongpart[j]][nexbelongpart[j]], prevans[cut][a][b]);
                                            currans[nex][nexbelongpart[j]][0] = plus(currans[nex][nexbelongpart[j]][0], prevans[cut][a][b]);
                                        }
                                    }
                                } else if (!a && b) {
                                    if (b != j) {
                                        currans[nex][nexbelongpart[j]][nexbelongpart[b]] = plus(currans[nex][nexbelongpart[j]][nexbelongpart[b]], prevans[cut][a][b]);
                                        currans[nex][0][nexbelongpart[b]] = plus(currans[nex][0][nexbelongpart[b]], prevans[cut][a][b]);
                                    } else {
                                        if (up) {
                                            if (jto > m) {
                                                continue;
                                            }
                                            currans[nex][nexbelongpart[j]][jto] = plus(currans[nex][nexbelongpart[j]][jto], prevans[cut][a][b]);
                                            currans[nex][0][jto] = plus(currans[nex][0][jto], prevans[cut][a][b]);
                                        } else {
                                            currans[nex][nexbelongpart[j]][nexbelongpart[j]] = plus(currans[nex][nexbelongpart[j]][nexbelongpart[j]], prevans[cut][a][b]);
                                            currans[nex][0][nexbelongpart[j]] = plus(currans[nex][0][nexbelongpart[j]], prevans[cut][a][b]);
                                        }
                                    }
                                } else {
                                    if (a != j && b != j) {
                                        currans[nex][nexbelongpart[a]][nexbelongpart[b]] = plus(currans[nex][nexbelongpart[a]][nexbelongpart[b]], prevans[cut][a][b]);
                                    } else if (a != j && b == j) {
                                        if (up) {
                                            if (jto > m) {
                                                continue;
                                            }
                                            currans[nex][nexbelongpart[a]][jto] = plus(currans[nex][nexbelongpart[a]][jto], prevans[cut][a][b]);
                                        } else {
                                            currans[nex][nexbelongpart[a]][nexbelongpart[b]] = plus(currans[nex][nexbelongpart[a]][nexbelongpart[b]], prevans[cut][a][b]);
                                        }
                                    } else if (a == j && b != j) {
                                        if (up) {
                                            if (jto > m) {
                                                continue;
                                            }
                                            currans[nex][jto][nexbelongpart[b]] = plus(currans[nex][jto][nexbelongpart[b]], prevans[cut][a][b]);
                                        } else {
                                            currans[nex][nexbelongpart[a]][nexbelongpart[b]] = plus(currans[nex][nexbelongpart[a]][nexbelongpart[b]], prevans[cut][a][b]);
                                        }
                                    } else {
                                        if (up) {
                                            currans[nex][jto][jto] = plus(currans[nex][jto][jto], prevans[cut][a][b]);
                                        } else {
                                            currans[nex][nexbelongpart[a]][nexbelongpart[b]] = plus(currans[nex][nexbelongpart[a]][nexbelongpart[b]], prevans[cut][a][b]);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            std::swap(prevans, currans);
        }
    }
    ul finalans = 0;
    for (ul cut : legalcuts) {
        for (ul a = 1; a <= m + 1; ++a) {
            finalans = plus(finalans, prevans[cut][a][a]);
        }
    }
    std::cout << finalans << std::endl;
    return 0;
}







C++11(clang++ 3.9) 解法, 执行用时: 12ms, 内存消耗: 1508K, 提交时间: 2018-09-04 13:05:41

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
#define MAXNUM 111111
using ll = long long;
ll mod = 1e9 + 7;
void add(ll &a, ll b)
{
	a += b;
	if (a >= mod)
		a -= mod;
}
const int hashsize = 111111;
typedef struct hashmap {
	int next[MAXNUM], pos[MAXNUM], first[hashsize], edgenum;
	long long totalnum, item[MAXNUM], itemkey[MAXNUM];
	void hadd(long long key, long long num)
	{
		int x = key % hashsize;
		for (int i = first[x]; i; i = next[i])
			if (itemkey[pos[i]] == key)
			{
				add(item[pos[i]], num);
				return;
			}
		next[edgenum] = first[x], pos[edgenum] = totalnum;
		first[x] = edgenum++;
		item[totalnum] = num, itemkey[totalnum] = key,
			totalnum++;
	}
	void init()
	{
		edgenum = 1, totalnum = 0;
		memset(first, 0, sizeof(first));
	}
}hashmap;
hashmap h[2];
int bit[22];
#define rep(i,start,end) for(int i=start;i<end;i++)
void getbit()
{
	for (int i = 0; i < 15; i++)
		bit[i] = 3 * i;
}
int n, m;
void decode(long long con, ll num[])
{
	rep(i, 0, m + 5)
	{
		num[i] = con & 7;
		con >>= 3;
	}
}
long long encode(ll num[])
{
	int count = 1;
	ll code[22];
	memset(code, -1, sizeof(code));
	code[0] = 0;
	long long st = 0;
	rep(i, 0, m)
	{
		if (code[num[i]] == -1)
			code[num[i]] = count++;
		long long x = code[num[i]];
		st |= (x << bit[i]);
	}
	rep(i, m, m + 2)
		if (code[num[i]] != -1)
			st |= (code[num[i]] << bit[i]);
	if (code[num[m]] > 0 && code[num[m + 1]] > 0 && num[m] == num[m + 1])
		num[m + 4] = 1;
	rep(i, m + 2, m + 5)
		st |= (num[i] << bit[i]);
	return st;
}

void connect(ll num2[], int s1, int s2)
{
	int k = min(s1, s2);
	rep(i, 0, m + 2)
		if (num2[i] == s1 || num2[i] == s2)
			num2[i] = k;
}
int sleft[22][22], sup[22][22];
long long res,num2[22];
void dp()
{
	bool type = 1;
	h[0].init();
	ll middlenum[22];
	h[0].hadd(0, 1);
	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++)
		{
			h[type].init();
			for (int k = 0; k < h[!type].totalnum; k++)
			{
				long long state = h[!type].itemkey[k],
					num = h[!type].item[k];
				decode(state, middlenum);
				int y1 = 2, y2 = 2;
				if (sleft[i][j] == 1)
					y1 = 1;
				if (sup[i][j] == 1)
					y2 = 1;
				rep(k1,0,y1)
					rep(k2, 0, y2)
				{
					if (!i&&k2)
						continue;
					if (!j&&k1)
						continue;
					rep(i2,0,2)
						rep(j2, 0, 2)
					{
						if (!i2&&middlenum[m + 2])
							continue;
						if (!j2&&middlenum[m + 3])
							continue;
						memcpy(num2, middlenum, (m + 5) * sizeof(ll));
						num2[j] = 15;
						if (k1)
							connect(num2, num2[j], middlenum[j - 1]);
						if (k2)
							connect(num2, num2[j], middlenum[j]);
						num2[m + 2] = i2, num2[m + 3] = j2;
						if (i2&&!middlenum[m+2])
							num2[m] = num2[j];
						if (j2&&!middlenum[m+3])
							num2[m + 1] = num2[j];
						h[type].hadd(encode(num2), num);
					}
				}
			}
			type = !type;
		}
	res = 0;
	rep(i, 0, h[!type].totalnum)
	{
		long long state = h[!type].itemkey[i],
			num = h[!type].item[i];
		decode(state, middlenum);
		if (middlenum[m + 4])
			add(res, num);
	}
}
int main(void)
{
	getbit();
	scanf("%d%d", &n, &m);
	rep(i, 0, n)
		rep(j, 1, m)
		scanf("%d", &sleft[i][j]);
	rep(i, 1, n)
		rep(j, 0, m)
		scanf("%d", &sup[i][j]);
	dp();
	printf("%lld\n", res);
}

上一题