哎。。。。。
都是泪。。。。。
这游戏太难了。。。。
再一次写了三天才AC。。。
生活为什么要这么艰难。。。。
妈蛋的啊。。。。
经过这一题之后我对插头DP理解更深了。。。。。只要是形成回路之后就不用再添加到装态里去了。。。。。。。
这次的代码也比前几次漂亮了不少,
当然是因为借鉴了别人的写法
AC代码如下:
四进制
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const __int64 digit[15] = { 1, 3, 9, 27, 81, 243, 729, 2187, 6561, 19683, 59049, 177147, 531441, 1594323, 4782969 };
const int mod = 10007;
struct HASHS{
__int64 statu[80010], cnt[80010];
int head[mod+10], next[80010], E;
int findhash( __int64 st ){
return st % mod;
}
void init(){
E = 0;
memset( head, -1, sizeof( head ) );
}
void add( __int64 st, __int64 num ){
int u = findhash( st );
for( int i = head[u]; i != -1; i = next[i] ){
if( statu[i] == st ){
cnt[i] += num;
return;
}
}
statu[E] = st;
cnt[E] = num;
next[E] = head[u];
head[u] = E++;
}
}biao[2];
int N, M;
char s[16][16];
int get( __int64 S,int p,int l=2)
{
return (S>>(p*l))&((1<<l)-1);
}
void set( __int64 &S,int p,int v,int l=2)
{
S^=get(S,p,l)<<(p*l);
S^=(v&((1<<l)-1))<<(p*l);
}
int find_r( int st, int j ){
int temp = 0, l;
for( l = j + 1; l <= M; l++ ){
__int64 ttt = get( st, l );
if( ttt == 2 ){
if( temp == 0 ){
break;
}else{
temp--;
}
}else if( ttt == 1 ){
temp++;
}
}
return l;
}
int find_l( int st, int j ){
int temp = 0, l;
for( l = j - 1; l >= 0; l-- ){
__int64 ttt = get( st, l );
if( ttt == 1 ){
if( temp == 0 ){
break;
}else{
temp--;
}
}else if( ttt == 2 ){
temp++;
}
}
return l;
}
__int64 solve(){
int now;
now = 1;
int lasti, lastj;
lasti = -1;
lastj = 1;
int flag = 1;
for( int i = N; i >= 1 && flag; i-- ){
for( int j = M; j >= 1 && flag; j-- ){
if( s[i][j] == 'O' ){
lasti = i;
lastj = j;
flag = 0;
}
}
}
__int64 ans = 0;
biao[0].init();
biao[1].init();
biao[1].add( 0, 1 );
now = 0;
for( int i = 1; i <= N; i++ ){
now ^= 1;
biao[now^1].init();
for( int k = 0; k < biao[now].E; k++ ){
__int64 st = biao[now].statu[k];
__int64 sum = biao[now].cnt[k];
biao[now^1].add( st << 2, sum );
}
for( int j = 0; j < M; j++ ){
now ^= 1;
biao[now^1].init();
for( int k = 0; k < biao[now].E; k++ ){
__int64 st = biao[now].statu[k];
__int64 sum = biao[now].cnt[k];
__int64 numj = get( st, j );
__int64 numj_1 = get( st, j + 1 );
if( s[i][j+1] == 'O' || s[i][j+1] == '*' ){
if( numj == 0 && numj_1 == 0 ){
if( s[i][j+1] == '*' ) biao[now^1].add( st, sum );
set( st, j, 1 );
set( st, j + 1, 2 );
if( j + 1 < M && s[i+1][j+1] != 'X' && s[i][j+2] != 'X' ) biao[now^1].add( st, sum );
}else if( numj == 0 || numj_1 == 0 ){
set( st, j, 0 );
set( st, j + 1, numj + numj_1 );
if( j + 1 < M && s[i][j+2] != 'X' ) biao[now^1].add( st, sum );
set( st, j, numj + numj_1 );
set( st, j + 1, 0 );
if( s[i+1][j+1] != 'X' ) biao[now^1].add( st, sum );
}else{
if( numj == 1 && numj_1 == 1 ){
int l = find_r( st, j + 1 );
if( l <= M ){
set( st, l, 1 );
set( st, j, 0 );
set( st, j + 1, 0 );
biao[now^1].add( st, sum );
}
}else if( numj == 2 && numj_1 == 2 ){
int l = find_l( st, j );
if( l >= 0 ){
set( st, l, 2 );
set( st, j, 0 );
set( st, j + 1, 0 );
biao[now^1].add( st, sum );
}
}else if( numj == 2 && numj_1 == 1 ){
set( st, j, 0 );
set( st, j + 1, 0 );
biao[now^1].add( st, sum );
}else{
set( st, j, 0 );
set( st, j + 1, 0 );
if( ( i > lasti || ( i == lasti && j + 1 >= lastj ) ) && !st ){
ans += sum;
}
}
}
}else{
if( numj == 0 && numj_1 == 0 ){
biao[now^1].add( st, sum );
}
}
}
}
}
return ans;
}
int main(){
int T, Case = 1;
cin >> T;
while( T-- ){
scanf( "%d%d", &N, &M );
memset( s, 0, sizeof( s ) );
for( int i = 1; i <= N; i++ ){
scanf( "%s", &s[i][1] );
}
printf( "Case %d: %I64d\n", Case++, solve() );
}
return 0;
}
三进制
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const __int64 digit[15] = { 1, 3, 9, 27, 81, 243, 729, 2187, 6561, 19683, 59049, 177147, 531441, 1594323, 4782969 };
const int mod = 10007;
struct HASHS{
__int64 statu[80010], cnt[80010];
int head[mod+10], next[80010], E;
int findhash( __int64 st ){
return st % mod;
}
void init(){
E = 0;
memset( head, -1, sizeof( head ) );
}
void add( __int64 st, __int64 num ){
int u = findhash( st );
for( int i = head[u]; i != -1; i = next[i] ){
if( statu[i] == st ){
cnt[i] += num;
return;
}
}
statu[E] = st;
cnt[E] = num;
next[E] = head[u];
head[u] = E++;
}
}biao[2];
int N, M;
char s[16][16];
int get( int k, int st ){
return ( st % digit[k+1] ) / digit[k];
}
int find_r( int st, int j ){
int temp = 0, l;
for( l = j + 1; l <= M; l++ ){
__int64 ttt = ( st % digit[l+1] ) / digit[l];
if( ttt == 2 ){
if( temp == 0 ){
break;
}else{
temp--;
}
}else if( ttt == 1 ){
temp++;
}
}
return l;
}
int find_l( int st, int j ){
int temp = 0, l;
for( l = j - 1; l >= 0; l-- ){
__int64 ttt = ( st % digit[l+1] ) / digit[l];
if( ttt == 1 ){
if( temp == 0 ){
break;
}else{
temp--;
}
}else if( ttt == 2 ){
temp++;
}
}
return l;
}
__int64 solve(){
int now;
int lasti, lastj;
lasti = -1;
lastj = 1;
int flag = 1;
for( int i = N; i >= 1 && flag; i-- ){
for( int j = M; j >= 1 && flag; j-- ){
if( s[i][j] == 'O' ){
lasti = i;
lastj = j;
flag = 0;
}
}
}
__int64 ans = 0;
// if( lasti == -1 ){
// ans += 1;
// }
biao[0].init();
biao[1].init();
biao[1].add( 0, 1 );
now = 0;
for( int i = 1; i <= N; i++ ){
now ^= 1;
biao[now^1].init();
for( int k = 0; k < biao[now].E; k++ ){
__int64 st = biao[now].statu[k];
__int64 sum = biao[now].cnt[k];
biao[now^1].add( st * 3, sum );
}
for( int j = 0; j < M; j++ ){
now ^= 1;
biao[now^1].init();
for( int k = 0; k < biao[now].E; k++ ){
__int64 st = biao[now].statu[k];
__int64 sum = biao[now].cnt[k];
__int64 numj = ( st % digit[j+1] ) / digit[j];
__int64 numj_1 = ( st % digit[j+2] ) / digit[j+1];
// __int64 tt = ( st % digit[M+2] ) / digit[M+1];
__int64 newt;
if( s[i][j+1] == 'O' || s[i][j+1] == '*' ){
if( numj == 0 && numj_1 == 0 ){
newt = st + digit[j] * ( 1 - numj ) + digit[j+1] * ( 2 - numj_1 );
if( j + 1 < M && s[i+1][j+1] != 'X' && s[i][j+2] != 'X' ) biao[now^1].add( newt, sum );
if( s[i][j+1] == '*' ) biao[now^1].add( st, sum );
}else if( numj == 0 || numj_1 == 0 ){
newt = st + digit[j] * ( 0 - numj ) + digit[j+1] * ( numj + numj_1 - numj_1 );
if( j + 1 < M && s[i][j+2] != 'X' ) biao[now^1].add( newt, sum );
newt = st + digit[j] * ( numj + numj_1 - numj ) + digit[j+1] * ( 0 - numj_1 );
if( s[i+1][j+1] != 'X' ) biao[now^1].add( newt, sum );
}else{
if( numj == 1 && numj_1 == 1 ){
int l = find_r( st, j + 1 );
if( l <= M ){
newt = st + digit[l] * ( 1 - 2 ) - digit[j] * numj - digit[j+1] * numj_1;
biao[now^1].add( newt, sum );
}
}else if( numj == 2 && numj_1 == 2 ){
int l = find_l( st, j );
if( l >= 0 ){
newt = st + digit[l] * ( 2 - 1 ) - digit[j] * numj - digit[j+1] * numj_1;
biao[now^1].add( newt, sum );
}
}else if( numj == 2 && numj_1 == 1 ){
newt = st - digit[j] * numj - digit[j+1] * numj_1;
biao[now^1].add( newt, sum );
}else{
// if( tt == 0 ){
newt = st - digit[j] * numj - digit[j+1] * numj_1;
if( ( i > lasti || ( i == lasti && j + 1 >= lastj ) ) && !newt ){
ans += sum;
}
// }
}
}
}else{
if( numj == 0 && numj_1 == 0 ){
biao[now^1].add( st, sum );
}
}
}
}
}
return ans;
}
int main(){
int T, Case = 1;
cin >> T;
while( T-- ){
scanf( "%d%d", &N, &M );
memset( s, 0, sizeof( s ) );
for( int i = 1; i <= N; i++ ){
scanf( "%s", &s[i][1] );
}
printf( "Case %d: %I64d\n", Case++, solve() );
}
return 0;
}
/*
100
3 3
**O
O**
*O*
12 12
OOOOOOOOOOOO
OOOOOOOOOOOO
OOOOOOOOOOOO
OOOOOOOOOOOO
OOOOOOOOOOOO
OOOOOOOOOOOO
OOOOOOOOOOOO
OOOOOOOOOOOO
OOOOOOOOOOOO
OOOOOOOOOOOO
OOOOOOOOOOOO
OOOOOOOOOOOO
4 4
XXOO
OOOO
OOOO
OOOO
4 4
OOOO
OOOO
OOOO
OOOO
*/