4月真是没写啥题,这题还是月初写的……

不错的插头dp,首先由n和m的范围知肯定是轮廓线是横向划的

问题的难点在于怎么处理下面两个问题

1.怎么处理独立插头

2.怎么处理完全将W和L左右隔开

先说独立插头,一开始我是增加独立插头位来处理的,一直wa……

后来意识到,因为独立插头一定是在第一行和最后一行唯一的,那么假定最顶部有m中状态,每种状态是一个位子上右下插头,最后一行类似处理,这样就解决了

完全将W和L左右隔开比较简单,这要看当前如果是W,则这个格子左边的下插头一定是偶数个,是L则为奇数个,画个图即可理解。

感觉自己插头dp的代码能力还是不足啊

 #include<bits/stdc++.h>

 using namespace std;
typedef long long ll;
const int mo=;
const int maxl=;
char s[];
int n,m,ans,en,p,a[][],v[],b[],c[]; struct node{
int p[mo],nex[maxl],len,f[maxl];
ll st[maxl];
void clr()
{
len=; memset(p,,sizeof(p));
}
void push(ll nw,int s)
{
int x=nw%mo;
for (int i=p[x];i!=-; i=nex[i])
if (st[i]==nw)
{
f[i]=min(f[i],s);
return;
}
st[++len]=nw; f[len]=s;
nex[len]=p[x]; p[x]=len;
}
} h[]; void get(ll st)
{
for (int i=m; i>=; i--)
{
c[i]=st&;
st>>=;
}
} ll put()
{
memset(v,,sizeof(v)); v[]=;
ll st=; int t=;
for (int i=; i<=m; i++)
{
if (v[b[i]]==-) v[b[i]]=++t;
b[i]=v[b[i]];
st<<=; st|=b[i];
}
return st;
} void shift()
{
for (int i=m;i; i--) b[i]=b[i-];
b[]=;
} int check(int j)
{
int f=;
for (int i=; i<=j; i++)
f+=(c[i]>);
return f;
} void dp(int i,int j)
{
for (int k=; k<=h[p^].len; k++)
{
ll st=h[p^].st[k];
get(st); int pw=h[p^].f[k];
int x=c[j-],y=c[j];
memcpy(b,c,sizeof(b));
if (a[i][j]>=)
{
if (x&&y)
{
if (x==y) continue;
b[j-]=b[j]=;
for (int r=; r<=m; r++)
if (b[r]==x) b[r]=y;
if (j==m) shift();
h[p].push(put(),pw+a[i][j]);
continue;
}
else if (x||y)
{
int r=x+y;
if (a[i][j+]>=)
{
b[j]=r; b[j-]=;
h[p].push(put(),pw+a[i][j]);
}
if (a[i+][j]>=||(i==n&&!check(j-)))
{
b[j]=; b[j-]=r;
if (j==m) shift();
h[p].push(put(),pw+a[i][j]);
}
}
else {
if (a[i][j+]>=&&(a[i+][j]>=||(i==n&&!check(j-))))
{
b[j]=b[j-]=m+;
h[p].push(put(),pw+a[i][j]);
}
b[j]=b[j-]=;
if (j==m) shift();
h[p].push(put(),pw);
}
}
else {
if (a[i][j]==-)
{
if (j==m) shift();
h[p].push(put(),pw);
continue;
}
int sd=check(j-);
if (!(sd&)&&a[i][j]==-) continue;
if (sd&&&a[i][j]==-) continue;
if (j==m) shift();
h[p].push(put(),pw);
}
}
} int main()
{
//freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
while (scanf("%d%d",&n,&m)!=EOF)
{
memset(a,,sizeof(a));
for (int i=; i<=n; i++)
{
scanf("%s",s+);
for (int j=; j<=m; j++)
{
int x=-;
if (s[j]=='#') x=-;
else if (s[j]=='W') x=-;
else if (s[j]=='L') x=-;
else x=s[j]-'';
a[i][j]=x;
}
}
ans=1e9+;
h[].clr(); h[].clr(); p=;
for (int i=; i<=m; i++)
if (a[][i]>=)
{
memset(b,,sizeof(b)); b[i]=;
h[].push(put(),);
}
for (int i=; i<=n; i++)
for (int j=; j<=m; j++)
{
p^=; h[p].clr();
dp(i,j);
// cout <<h[p].len<<" "<<i<<" "<<j<<endl;
}
for (int k=; k<=h[p].len; k++)
{
get(h[p].st[k]);
int sd=check(m);
if (sd==) ans=min(ans,h[p].f[k]);
}
if (ans==) puts("-1"); else printf("%d\n",ans);
}
}

hdu4796的更多相关文章

随机推荐

  1. Python3 字典 pop() 方法

     Python3 字典 描述 Python 字典 pop() 方法删除字典给定键 key 所对应的值,返回值为被删除的值.key值必须给出. 否则,返回default值. 语法 pop()方法语法: ...

  2. 洛谷P1195 口袋的天空

    口袋的天空 327通过 749提交 题目提供者该用户不存在 标签云端 难度普及+/提高 时空限制1s / 128MB 提交  讨论  题解 最新讨论更多讨论 暂时没有讨论 题目背景 小杉坐在教室里,透 ...

  3. java 注解详解

    先引用一下百度百科的名词解析: 定义:注解(Annotation),也叫元数据.一种代码级别的说明.它是JDK1.5及以后版本引入的一个特性,与类.接口.枚举是在同一个层次.它可以声明在包.类.字段. ...

  4. win7 64位环境下配置汇编环境和程序设计

    下载dosbox,并解压安装 下载地址: http://pan.baidu.com/s/1eRJbJAq 默认安装到C:\Program Files (x86)\DOSBox-0.74 安装成功后,双 ...

  5. python中如何优雅使用import

    http://note.youdao.com/noteshare?id=c55be6a8565f5eb586aa52244b3af010

  6. 隐藏超出父元素的子元素的部分:overflow

    overflow : 针对超出父级的内容如何显示 值: visible 默认值,超出的内容会显示出来 auto 如果内容超出了父级,那就出现滚动条.如果内容没有超出,就没有滚动条 hidden 超出的 ...

  7. cc1: warnings being treated as errors解决办法

    安装GDB时出现cc1: warnings being treated as errors Edit the Makefile and delete this line:WERROR_CFLAGS = ...

  8. 多例模式,保证实例的唯一性,仅适用于form窗体

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.W ...

  9. Packet Tracer 5.0 构建CCNA实验(3)—— 路由器实现vlan间通信

    --交换机配置 --交换机和路由器连接的接口 switchport mode trunk --路由器配置 enable conf t int fa0/0.1 --路由器接口的子接口 encapsula ...

  10. 不用注解添加controller抛出No adapter for handler异常

    不用注解添加controller时会抛出No adapter for handler异常. 解决方法:在DispatcherServlet的配置文件(***-servlet.xml)中加入如下两行: ...