码迷,mamicode.com
首页 > 其他好文 > 详细

CF293B Distinct Paths

时间:2019-10-30 00:10:37      阅读:178      评论:0      收藏:0      [点我收藏+]

标签:etc   答案   tin   class   ret   namespace   reg   math   bit   

首先这个题有一个坑点(?):当\(n+m-1>k\)时无解.显然嘛

所以\(n,m\leq1000\)?假的.

于是我们就可以愉快(?)的搜索了.

但是\(k^{n*m}\)依旧非常大,于是我们开始剪枝.

  • 可行性剪枝:如果剩下的颜色不足以支持剩下的路程,就直接\(return\).
  • 我们可以对于同一类数字(即输入数据中没有出现过的颜色)的答案直接算一个后乘这类数字的个数.

还有对于之前的颜色存储,可以使用状态压缩.

我是不会告诉你这样不卡常是过不了的

#pragma GCC optimize("Ofast,inline", 3)
#include<bits/stdc++.h>
#define il inline
#define rg register
#define gi read<int>
using namespace std;
const int mod = 1e9 + 7;
template<class TT>
il TT read() {
    TT o = 0,fl = 1; char ch = getchar();
    while (!isdigit(ch) && ch != '-') ch = getchar();
    if (ch == '-') fl = -1, ch = getchar();
    while (isdigit(ch)) o = o * 10 + ch - '0', ch = getchar();
    return fl * o;
}
int status[15][15], mp[15][15], cnt[15], num[2010], n, m, k;
int dfs(int x, int y) {
    if (y == m + 1) ++x, y = 1;
    if (x == n + 1) return 1;
    status[x][y] = status[x - 1][y] | status[x][y - 1];
    int res = 0, lst = -1;
    if (n + m - x - y + 1 > k - num[status[x][y]]) return 0;
    if (mp[x][y] != -1) {
        if ((1 << mp[x][y]) & status[x][y]) return 0;
        status[x][y] |= 1 << mp[x][y]; ++cnt[mp[x][y]];
        res = dfs(x, y + 1);
        status[x][y] ^= 1 << mp[x][y]; --cnt[mp[x][y]];
        return res;
    }
    for (int i = 0; i < k; ++i)
        if (!((1 << i) & status[x][y])) {
            status[x][y] |= 1 << i; ++cnt[i];
            if (cnt[i] == 1) {
                if (lst == -1) lst = dfs(x, y + 1);
                res += lst;
            }
            else res += dfs(x, y + 1);
            res > mod ? res -= mod : 0;
            status[x][y] ^= 1 << i; --cnt[i];
        }
    return res;
}
int main() {
    for (int i = 1; i <= 2000; ++i) num[i] = num[i >> 1] + (i & 1);
    n = gi(), m = gi(), k = gi();
    if (n + m - 1 > k) return puts("0") & 0;
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j)
            mp[i][j] = gi() - 1, ++cnt[mp[i][j]];
    printf("%d\n", dfs(1, 1));
    return 0;
}

CF293B Distinct Paths

标签:etc   答案   tin   class   ret   namespace   reg   math   bit   

原文地址:https://www.cnblogs.com/lylyl/p/11762235.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!