BZOJ 1814 Ural 1519 Formula 1

题目链接

https://www.lydsy.com/JudgeOnline/problem.php?id=1814

题解

插头dp,枚举边界线的插头,分类讨论转移点上插头和左插头的情况,来转移这个点的插头。

代码

#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn=20;
const int hash_mod=1007;
const int maxd=maxn*maxn;
const int maxk=50000;

int read()
{
  int x=0,f=1;
  char ch=getchar();
  while((ch<'0')||(ch>'9'))
    {
      if(ch=='-')
        {
          f=-f;
        }
      ch=getchar();
    }
  while((ch>='0')&&(ch<='9'))
    {
      x=x*10+ch-'0';
      ch=getchar();
    }
  return x*f;
}

struct func
{
  int x;
  long long y;
};

struct hash_table
{
  int now[hash_mod+10],pre[maxk+2],cnt;
  func val[maxk+2];

  int clear()
  {
    cnt=0;
    memset(now,0,sizeof now);
    return 0;
  }

  long long add(int s,long long v)
  {
    int trans=s%hash_mod,j=now[trans];
    while(j)
      {
        if(val[j].x==s)
          {
            val[j].y+=v;
            return val[j].y;
          }
        j=pre[j];
      }
    val[++cnt].x=s;
    val[cnt].y=v;
    pre[cnt]=now[trans];
    now[trans]=cnt;
    return v;
  }

  func get(int x)
  {
    return val[x];
  }
};

hash_table ht[2];
int n,m,rv[maxn+4],v[maxn+2][maxd+2],now,last;
char s[maxn+4];

int decode(int x)
{
  for(int i=0; i<=m; ++i)
    {
      rv[i]=x&3;
      x>>=2;
    }
  return 0;
}

int encode()
{
  int res=0;
  for(int i=m; ~i; --i)
    {
      res=(res<<2)+rv[i];
    }
  return res;
}

int findl(int pos)
{
  int now=-1;
  while(1)
    {
      if(rv[pos])
        {
          now+=(rv[pos]==1)?1:-1;
        }
      if(!now)
        {
          return pos;
        }
      --pos;
    }
}

int findr(int pos)
{
  int now=1;
  while(1)
    {
      if(rv[pos])
        {
          now+=(rv[pos]==1)?1:-1;
        }
      if(!now)
        {
          return pos;
        }
      ++pos;
    }
}

int expand(int x,int y,func from)
{
  decode(from.x);
  int west=rv[m],north=rv[y];
  if((!y)&&west)
    {
      return 0;
    }
  if(v[x][y])
    {
      if(west||north)
        {
          return 0;
        }
      ht[now].add(encode(),from.y);
    }
  else if(west&&north)
    {
      rv[m]=rv[y]=0;
      if(west<north)
        {
          int flag=0;
          for(int i=0; i<=m; ++i)
            {
              if(rv[i])
                {
                  flag=1;
                  break;
                }
            }
          if(!((!flag)&&(x==n)))
            {
              return 0;
            }
        }
      if(west==north)
        {
          if(west==1)
            {
              rv[findr(y+1)]=1;
            }
          else
            {
              rv[findl(y-1)]=2;
            }
        }
      ht[now].add(encode(),from.y);
    }
  else if((!west)&&(!north))
    {
      rv[y]=1;
      rv[m]=2;
      ht[now].add(encode(),from.y);
    }
  else if((!west)&&north)
    {
      ht[now].add(encode(),from.y);
      rv[m]=north;
      rv[y]=0;
      ht[now].add(encode(),from.y);
    }
  else if(west&&(!north))
    {
      ht[now].add(encode(),from.y);
      rv[y]=west;
      rv[m]=0;
      ht[now].add(encode(),from.y);
    }
  return 0;
}

int work()
{
  now=0;
  last=1;
  ht[0].clear();
  ht[0].add(0,1);
  for(int i=1; i<=n; ++i)
    {
      for(int j=0; j<m; ++j)
        {
          std::swap(now,last);
          ht[now].clear();
          for(int k=1; k<=ht[last].cnt; ++k)
            {
              expand(i,j,ht[last].get(k));
            }
        }
    }
  return 0;
}

int main()
{
  n=read();
  m=read();
  for(int i=1; i<=n; ++i)
    {
      scanf("%s",s);
      for(int j=0; j<m; ++j)
        {
          if(s[j]=='*')
            {
              v[i][j]=1;
            }
        }
    }
  work();
  printf("%lld\n",ht[now].add(0,0));
  return 0;
}

转载于:https://www.cnblogs.com/Canopus-wym/p/10376163.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值