poj 1739 插头DP

和上一题很像,只需要增加两行就行。。。

还有hash要开小一点。。。。不然会TLE

AC代码如下:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <map>
using namespace std;

const long long digit[15] = { 1, 3, 9, 27, 81, 243, 729, 2187, 6561, 19683, 59049, 177147, 531441, 1594323, 4782969 };
char maps[13][13];
long long N, M;

//   哈希表
#define LL long long

const int mod = 10007;

struct HASH{
    int head[mod+10], E, next[80000];
    LL val[10000], cnt[10000];

    void init() {
        memset(head, -1, sizeof(head));
        E = 0;
    }

    int findhash(LL x) {
        return (x%mod + mod)%mod;
    }

    void add(LL x, LL sum) {
        int u = findhash(x);
        for(int i = head[u];i != -1;i = next[i]) if(val[i] == x) {
            cnt[i] += sum;
            return ;
        }
        val[E] = x;
        cnt[E] = sum;
        next[E] = head[u];
        head[u] = E++;
    }

}biao1, biao2;

//

void init(){
	memset( maps, 0, sizeof( maps ) );
    for( int i = 1; i <= N; i++ ){
        scanf( "%s", &maps[i][1] );
    }
	for( int j = 2; j <= M - 1; j++ ){
		maps[N+1][j] = '#';
	}
	maps[N+1][1] = maps[N+1][M] = '.';
	for( int j = 1; j <= M; j++ ){
		maps[N+2][j] = '.';
	}
	N += 2;
}

long long solve(){
    int lasti, lastj;
	long long ans;
	long long code[13];
    lasti = -1;
    lastj = -1;
    int flag = 0;
    for( int i = N; i >= 1 && !flag; i-- ){
        for( int j = M; j >= 1 && !flag; j-- ){
            if( maps[i][j] == '.' ){
                lasti = i;
                lastj = j;
                flag = 1;
                break;
            }
        }
    }
	if( lasti == -1 ){
		return 0;
	}
	biao1.init();
	biao2.init();
	biao2.add( 0, 1 );
	ans = 0;
    for( int i = 1; i <= N; i++ ){
		biao1.init();
		for( int k = 0; k < biao2.E; k++ ){
			long long tid, tsum;
			tid = biao2.val[k];
			tsum = biao2.cnt[k];
			biao1.add( tid * 3, tsum );
		}
		for( int j = 0; j < M; j++ ){
			biao2.init();
			for( int k = 0; k < biao1.E; k++ ){
				long long tid, tsum;
				tid = biao1.val[k];
				tsum = biao1.cnt[k];
				long long numj, numj1;
				numj = ( tid % digit[j+1] ) / digit[j];
				numj1 = ( tid % digit[j+2] ) / digit[j+1];
				if( maps[i][j+1] == '.' ){
					if( numj == 0 && numj1 == 0 ){
						long long tt = tid - digit[j] * numj - digit[j+1] * numj1 + digit[j] * 1 + digit[j+1] * 2;
						if( j + 1 < M ) biao2.add( tt, tsum );
					}else if( numj == 0 || numj1 == 0 ){
					    int temp = numj + numj1;
						long long tt = tid + digit[j] * temp - digit[j] * numj - digit[j+1] * numj1;
						biao2.add( tt, tsum );
					    tt = tid - digit[j] * numj - digit[j+1] * numj1 + digit[j+1] * temp;
					    if( j + 1 < M ) biao2.add( tt, tsum );
					}else{
					    if( numj == 1 && numj1 == 1 ){
					        int temp = 0;
							int l;
					        for( l = j + 2; l <= M; l++ ){
								long long ttt = tid % digit[l+1] / digit[l];
								if( ttt == 2 ){
					                if( temp == 0 ){
					                    break;
					                }else{
					                    temp--;
					                }
					            }else if( ttt == 1 ){
					                temp++;
					            }
					        }
							if( l <= M ){
								long long ttt = tid % digit[l+1] / digit[l];
								long long tt = tid - digit[j] * numj - digit[j+1] * numj1 + digit[l] * ( 1 - ttt );
								biao2.add( tt, tsum );
							}
					    }else if( numj == 2 && numj1 == 2 ){
					        int temp = 0;
							int l;
					        for( l = j - 1; l >= 0; l-- ){
								int ttt = tid % digit[l+1] / digit[l];
					            if( ttt == 1 ){
					                if( temp == 0 ){
					                    break;
					                }else{
					                    temp--;
					                }
					            }else if( ttt == 2 ){
					                temp++;
					            }
					        }
							if( l >= 0 ){
								long long ttt = tid % digit[l+1] / digit[l];
								long long tt = tid - digit[j] * numj - digit[j+1] * numj1 + digit[l] * ( 2 - ttt );
								biao2.add( tt, tsum );
							}
					    }else if( numj == 1 && numj1 == 2 ){
					        long long tt = tid - digit[j] * numj - digit[j+1] * numj1;
					        if( i == lasti && j + 1 == lastj && !tt ){
					            biao2.add( tt, tsum );
								ans += tsum;
					        }
					    }else{
							long long tt = tid - digit[j] * numj - digit[j+1] * numj1;
							biao2.add( tt, tsum );
					    }
					}
				}else{
					if( numj == 0 && numj1 == 0 ){
						biao2.add( tid, tsum );
					}
				}
            }
			biao1 = biao2;
        }
    }
    return ans;
}

int main(){
    while( cin >> N >> M && !( N == 0 && M == 0 ) ){
        init();
        printf( "%lld\n", solve() );
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值