题目链接
题意
给出n*m的方格,有些格子不能铺线,其它格子必须铺,可以形成多个闭合回路。问有多少种铺法?
思路
是 点我 这题的弱化版,可以不考虑插头的括号方向,将合并插头操作允许在每个位置出现即可。
注意全0也是存在1种方案。。
代码
不考虑插头的左右
#include <bits/stdc++.h>
using namespace std;
#define ll long long
struct hash_table {
ll hash_mod = 590027;
ll state[600000], ans[600000], up;
ll tot, first[600000], nxt[600000], w[600000];
void init() {
memset(first, 0, sizeof(first));
tot = 0;
up = 0;
}
ll ins(ll sta, ll val) {
ll key = sta%hash_mod;
for(ll i = first[key]; i; i = nxt[i]) {
if(state[w[i]] == sta) return ans[w[i]] += val;
}
state[++up] = sta;
ans[up] = val;
nxt[++tot] = first[key];
w[tot] = up;
first[key] = tot;
return val;
}
}dp[2];
/*hash_table*/
// chatou 0 null, 1 right, 2 down
ll n, m, endx, endy, a[15][15], bit[15];
#define prel (1ll<<bit[j-1])
#define prer (1ll<<bit[j])
void solve() {
ll cur = 0, ans = 0;
dp[cur].init();
dp[0].ins(0,1);
for(ll i = 1; i <= n; ++i) {
for(ll j = 1; j <= dp[cur].up; ++j) dp[cur].state[j] <<= 1;
for(ll j = 1; j <= m; ++j) {
cur ^= 1;
dp[cur].init();
for(ll k = 1; k <= dp[cur^1].up; ++k) {
ll sta = dp[cur^1].state[k];
ll w = dp[cur^1].ans[k];
ll d = (sta>>bit[j])&1ll;
ll r = (sta>>bit[j-1])&1ll;
if(!a[i][j]) {
if(!d && !r) dp[cur].ins(sta,w);
}
else if(!d && !r) {
if(a[i+1][j] && a[i][j+1]) dp[cur].ins(sta + prel + prer,w);
}
else if(!d && r) {
if(a[i+1][j]) dp[cur].ins(sta,w);
if(a[i][j+1]) dp[cur].ins(sta-prel+prer,w);
}
else if(d && !r) {
if(a[i+1][j]) dp[cur].ins(sta+prel-prer,w);
if(a[i][j+1]) dp[cur].ins(sta,w);
}
else {
dp[cur].ins(sta-prel-prer,w);
}
}
}
}
printf("%lld\n",dp[cur].ins(0,0));
}
int main() {
ll t;
for(scanf("%lld",&t); t; --t) {
scanf("%lld%lld",&n,&m);
memset(a,0,sizeof(a));
for(ll i = 1; i <= n; ++i) {
for(ll j = 1; j <= m; ++j) {
scanf("%d",&a[i][j]);
if(a[i][j]) {
endx = i;
endy = j;
}
}
}
for(ll i = 1; i <= 13; ++i) bit[i] = i;
solve();
}
return 0;
}
下为考虑插头的左右,直接CV了上题的代码改改。
STL unordered_map
#include <bits/stdc++.h>
using namespace std;
#define ll long long
unordered_map<ll,ll> dp[3];
// chatou 0 null, 1 right, 2 down
ll n, m, endx, endy, a[15][15], bit[15];
#define prel (1ll<<bit[j-1])
#define prer (1ll<<bit[j])
void solve() {
ll cur = 0, ans = 0;
dp[cur].clear();
dp[0][0] = 1;
for(ll i = 1; i <= n; ++i) {
dp[2].clear();
for(auto j : dp[cur]) dp[2][j.first<<2] = j.second;
dp[cur] = dp[2];
for(ll j = 1; j <= m; ++j) {
cur ^= 1;
dp[cur].clear();
for(auto k : dp[cur^1]) {
ll sta = k.first;
ll w = k.second;
ll d = (sta>>bit[j])&3ll;
ll r = (sta>>bit[j-1])&3ll;
// printf("%lld %lld - %lld %lld\n",i,j,sta,w);
// printf("%lld = %lld\n\n",r,d);
if(!a[i][j]) {
if(!r && !d) dp[cur][sta] += w;
}
else if(!r && !d) {
if(a[i+1][j] && a[i][j+1]) dp[cur][sta + prel + (2*prer)] += w;
}
else if(r && !d) {
if(a[i+1][j]) dp[cur][sta] += w;
if(a[i][j+1]) dp[cur][sta - (r*prel) + (r*prer)] += w;
}
else if(!r && d) {
if(a[i+1][j]) dp[cur][sta + (d*prel) - (d*prer)] += w;
if(a[i][j+1]) dp[cur][sta] += w;
}
else if(r == 1 && d == 1) {
ll cnt = 1;
for(ll p = j+1; p <= m; ++p) {
if(((sta>>bit[p])&3ll) == 1) ++cnt;
if(((sta>>bit[p])&3ll) == 2) --cnt;
if(!cnt) {
dp[cur][(sta - (r*prel) - (d*prer)) - (1<<bit[p])] += w;
break;
}
}
}
else if(r == 2 && d == 2) {
ll cnt = 1;
for(ll p = j-2; p >= 0; --p) {
if(((sta>>bit[p])&3ll) == 1) --cnt;
if(((sta>>bit[p])&3ll) == 2) ++cnt;
if(!cnt) {
dp[cur][(sta - (r*prel) - (d*prer)) + (1<<bit[p])] += w;
break;
}
}
}
else if(r == 2 && d == 1) {
dp[cur][sta - (r*prel) - (d*prer)] += w;
}
else if(r == 1 && d == 2) { // ok
dp[cur][sta - (r*prel) - (d*prer)] += w;
if(i == endx && j == endy) ans += w;
}
}
}
}
printf("%lld\n",dp[cur][0]);
}
int main() {
ll t;
for(scanf("%lld",&t); t; --t) {
scanf("%lld%lld",&n,&m);
memset(a,0,sizeof(a));
for(ll i = 1; i <= n; ++i) {
for(ll j = 1; j <= m; ++j) {
scanf("%lld",&a[i][j]);
if(a[i][j]) {
endx = i;
endy = j;
}
}
}
for(ll i = 1; i <= 13; ++i) bit[i] = i<<1;
solve();
}
return 0;
}
hash_table
#include <bits/stdc++.h>
using namespace std;
#define ll long long
struct hash_table {
ll hash_mod = 590027;
ll state[600000], ans[600000], up;
ll tot, first[600000], nxt[600000], w[600000];
void init() {
memset(first, 0, sizeof(first));
tot = 0;
up = 0;
}
ll ins(ll sta, ll val) {
ll key = sta%hash_mod;
for(ll i = first[key]; i; i = nxt[i]) {
if(state[w[i]] == sta) return ans[w[i]] += val;
}
state[++up] = sta;
ans[up] = val;
nxt[++tot] = first[key];
w[tot] = up;
first[key] = tot;
return val;
}
}dp[2];
/*hash_table*/
// chatou 0 null, 1 right, 2 down
ll n, m, endx, endy, a[15][15], bit[15];
#define prel (1ll<<bit[j-1])
#define prer (1ll<<bit[j])
void solve() {
ll cur = 0, ans = 0;
dp[cur].init();
dp[0].ins(0,1);
for(ll i = 1; i <= n; ++i) {
for(ll j = 1; j <= dp[cur].up; ++j) dp[cur].state[j] <<= 2;
for(ll j = 1; j <= m; ++j) {
cur ^= 1;
dp[cur].init();
for(ll k = 1; k <= dp[cur^1].up; ++k) {
ll sta = dp[cur^1].state[k];
ll w = dp[cur^1].ans[k];
ll d = (sta>>bit[j])&3ll;
ll r = (sta>>bit[j-1])&3ll;
// printf("%lld %lld - %lld %lld\n",i,j,sta,w);
// printf("%lld = %lld\n\n",r,d);
if(!a[i][j]) {
if(!r && !d) dp[cur].ins(sta,w);
}
else if(!r && !d) {
if(a[i+1][j] && a[i][j+1]) dp[cur].ins(sta + prel + (2*prer),w);
}
else if(r && !d) {
if(a[i+1][j]) dp[cur].ins(sta,w);
if(a[i][j+1]) dp[cur].ins(sta - (r*prel) + (r*prer),w);
}
else if(!r && d) {
if(a[i+1][j]) dp[cur].ins(sta + (d*prel) - (d*prer),w);
if(a[i][j+1]) dp[cur].ins(sta,w);
}
else if(r == 1 && d == 1) {
ll cnt = 1;
for(ll p = j+1; p <= m; ++p) {
if(((sta>>bit[p])&3ll) == 1) ++cnt;
if(((sta>>bit[p])&3ll) == 2) --cnt;
if(!cnt) {
dp[cur].ins((sta - (r*prel) - (d*prer)) - (1<<bit[p]),w);
break;
}
}
}
else if(r == 2 && d == 2) {
ll cnt = 1;
for(ll p = j-2; p >= 0; --p) {
if(((sta>>bit[p])&3ll) == 1) --cnt;
if(((sta>>bit[p])&3ll) == 2) ++cnt;
if(!cnt) {
dp[cur].ins((sta - (r*prel) - (d*prer)) + (1<<bit[p]),w);
break;
}
}
}
else if(r == 2 && d == 1) {
dp[cur].ins(sta - (r*prel) - (d*prer),w);
}
else if(r == 1 && d == 2) { // ok
dp[cur].ins(sta - (r*prel) - (d*prer),w);
if(i == endx && j == endy) ans += w;
}
}
}
}
printf("%lld\n",dp[cur].ins(0,0));
}
int main() {
ll t;
for(scanf("%lld",&t); t; --t) {
scanf("%lld%lld",&n,&m);
memset(a,0,sizeof(a));
for(ll i = 1; i <= n; ++i) {
for(ll j = 1; j <= m; ++j) {
scanf("%d",&a[i][j]);
if(a[i][j]) {
endx = i;
endy = j;
}
}
}
for(ll i = 1; i <= 13; ++i) bit[i] = i<<1;
solve();
}
return 0;
}