CodeForces 115C. Plumber 解题报告

题目

题意:

n×m的的矩阵里,每个格子都有一个水管,并且水管是给出的4种形状的一个。有一些地方水管已经确定了,有一些还没有。若两个相邻的水管彼此没有连通则为泄漏。求不泄漏的方案数,不要求水管全部连成一条。

题解:

原本以为是简单的插头DP,但是看数据规模不可能。根据给出的四种水管,可知任何一种都和左右两格连且只连一个,上下也是,而且左右和上下是独立的,所以可以单独考虑一行和一列。

对一行而言,如果有已经确定的水管,要判断是否能满足:两根相邻的水管的距离和朝向是否相同。如果没有确定的,那么第一根水管可以连边界或者第二根,其后的水管在水平方向就全确定了而且一定有解。

竖直方向同理。


//Time:218ms
//Memory:10000KB
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <vector>
#include <map>
#include <queue>
#include <set>
#define MAXN 100010
#define INF 1000000007
#define MP(x,y) make_pair(x,y)
#define FI first
#define SE second
#define EPS 1e-8
using namespace std;
char **ma;
int ty[2][4]={{1,1,0,0},{1,0,0,1}};
int pow_mod(long long a,int p,int mod)
{
    long long ret=1;
    while(p)
    {
        if(p&1) ret=ret*a%mod;
        a=a*a%mod,p>>=1;
    }
    return ret;
}
int main()
{
    int n,m,cnt;
    while(scanf("%d%d",&n,&m)==2)
    {
        cnt=0;
        bool flag=1;
        ma=new char *[n];
        for(int i=0;i<n;++i)
        {
            int pre=-1;
            bool tmp=1;
            ma[i]=new char [m+1];
            scanf("%s",ma[i]);
            for(int j=0;j<m;++j)
                if(ma[i][j]>='0')
                {
                    ma[i][j]-='1';
                    if(pre!=-1)
                        flag&=((j-pre)&1)==(ty[0][ma[i][j]]^ty[0][ma[i][pre]]);
                    pre=j;
                    tmp=0;
                }
            if(tmp)    ++cnt;
        }
        for(int i=0;i<m&&flag;++i)
        {
            int pre=-1;
            bool tmp=1;
            for(int j=0;j<n;++j)
                if(ma[j][i]<=3)
                {
                    if(pre!=-1)
                        flag&=((j-pre)&1)==(ty[1][ma[j][i]]^ty[1][ma[pre][i]]);
                    pre=j;
                    tmp=0;
                }
            if(tmp)    ++cnt;
        }
        printf("%d\n",flag?pow_mod(2,cnt,1000003):0);
        for(int i=0;i<n;++i)    delete ma[i];
        delete ma;
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值