第四场春训,谢谢zzh学长 qwq!
(DP还有好多坑没填啊 )
【BUAA Spring Training 04】
Tags:斜率优化 决策单调性优化 状压dp 错排 树形dp
Problem C. 玉米地
[C] 题意
给定一个玉米地二维 01 \text{01} 01 矩阵(行列数: 1 ≤ R , C ≤ 12 1 \le R,C \le 12 1≤R,C≤12), 1 \text{1} 1 表示可种, 0 \text{0} 0 表示不可种
现在要种地,只能种在可种的格子,然后种的格子之间不能有公共边(不能连着左右或上下种,可以斜对角着种)
问一共有多少种种法,对 100000000 \text{100000000} 100000000 取模。
[C] 思路
看着这范围… 果断状压dp呀。
初始化就是枚举第一行,选出合法的,dp值为1。
接下来逐行枚举,先枚举这一行合法的,再枚举上一行存在的,然后转移计数。
时间复杂度: O ( 2 2 C × R ) O(2^{2C} \times R) O(22C×R)
[C] 代码
/*
* If we give,
* all we've got,
* we will make it through.
*/
#include <cstdio>
#include <cstdlib>
#define GC getchar()
#define _SN(x) {char _c=GC,_v=1;for(x=0;_c<48||_c>57;_c=GC)if(_c==45)_v=-1;for(;_c>=48&&_c<=57;x=(x<<1)+(x<<3)+_c-48,_c=GC);if(_v==-1)x=-x;}
#define _SAN(a,n) {int _i=0,_n=n;for(;_i<_n;++_i)_SN(a[_i])}
#define _SA(a,l,r) {int _i=l,_r=r;for(;_i<_r;++_i)_SN(a[_i])}
#define _gS(_1, _2, _3, _sc, ...) _sc
#define sc(...) _gS(__VA_ARGS__,_SA,_SAN,_SN, ...)(__VA_ARGS__)
#define _G1(_1) ({int _1;sc(_1)_1;})
#define _G2(_1,_2) int _1,_2;sc(_1)sc(_2)
#define _G3(_1,_2,_3) int _1,_2,_3;sc(_1)sc(_2)sc(_3)
#define _gG(_1,_2,_3,_get, ...) _get
#define get(...) _gG(__VA_ARGS__,_G3,_G2,_G1, ...)(__VA_ARGS__)
#define _F0N(i,n) for(int i=0;i<(n);++i)
#define _FLR(i,l,r) for(int i=(l);i<(r);++i)
#define _gF(_1, _2, _3, _F, ...) _F
#define F(...) _gF(__VA_ARGS__,_FLR,_F0N, ...)(__VA_ARGS__)
#define _FD0(i,n) for(int i=0;i<=(n);++i)
#define _FDL(i,l,r) for(int i=(l);i<=(r);++i)
#define _gFD(_1, _2, _3, _FD, ...) _FD
#define FD(...) _gFD(__VA_ARGS__,_FDL,_FD0, ...)(__VA_ARGS__)
#define FRC(R,C) for(int r=0;r<R;++r)for(int c=0;c<C;++c)
#define IL inline
#define PC putchar
template<class T>void PRT(const T _){if(_<0){PC(45),PRT(-_);return;}if(_>=10)PRT(_/10);PC(_%10+48);}
template<class T>void UPRT(const T _){if(_>=10)UPRT(_/10);PC(_%10+48);}
typedef unsigned long bint;
const int MN = 14, MP = 1<<12|1;
const bint MOD = 100000000;
bint mask[MN], dp[MN][MP];
template <typename T>
IL void inc(T &self, const T off)
{
if ((self+=off) >= MOD)
self -= MOD;
}
IL bool check_self(const int r, const bint state)
{
for (bint sta=state; sta; sta>>=1)
if ((sta & 1) && (sta & 2))
return false;
return !(state & mask[r]);
}
IL bool check(const bint state, const bint pre_sta)
{
return !(state & pre_sta);
}
int main()
{
get(R, C)
FRC(R, C)
mask[r] |= !get(tp) << c;
const bint MAX_STATE = 1u<<C;
for (bint now=0; now<MAX_STATE; ++now)
if (check_self(0, now))
dp[0][now] = 1;
F(r, 1, R)
for (bint now=0; now<MAX_STATE; ++now)
for (bint prev=0; prev<MAX_STATE; ++prev)
if (dp[r-1][prev] && check_self(r, now) && check(now, prev))
inc(dp[r][now], dp[r-1][prev]);
bint sum = 0;
for (bint now=0; now<MAX_STATE; ++now)
inc(sum, dp[R-1][now]);
UPRT(sum);
return 0;
}
Problem A.
(待更)