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. win7 64位环境下配置汇编环境和程序设计

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

  2. spring整合hibernate时报错:org.hibernte.engine.transaction.spi.transactioncontext

    错误提示:Caused by:java.lang.ClassNotFoundException: org.hibernte.engine.transaction.spi.transactioncont ...

  3. 779D. String Game 二分 水

    Link 题意: 给出两字符串$a$,$b$及一个序列,要求从前往后按照序列删掉$a$上的字符,问最少删多少使$b$串不为a的子串 思路: 限制低,直接二分答案,即二分序列位置,不断check即可. ...

  4. Python进行数据分析(一)初步学习 对时区进行计数

    time_zones[:10] Out[19]: [u'America/New_York', u'America/Denver', u'America/New_York', u'America/Sao ...

  5. JAVA中反射机制二

    声明:如需转载请说明地址来源:http://www.cnblogs.com/pony1223 反射二 利用反射创建对象 1.利用反射创建对象,首先我们创建一个类,类里面,我们知道构造函数有默认的构造函 ...

  6. SDUT 3917

    UMR 现在手里有 n 张康纳的表情,最上面一张是玛吉呀巴库乃.现在 UMR 如果每次把最上面的 m 张牌移到最下面而不改变他们的顺序及朝向,那么至少经过多少次移动玛吉呀巴库乃才会又出现在最上面呢? ...

  7. 设置display:inline-block产生间隙

    display:inline-block产生间隙,是由于换行在内的空白符 display:inline-block在IE下仅仅是触发了layout,而它本是行布局,触发后,块元素依然还是行布局.所以需 ...

  8. 蓝色的cms网站后台管理模板——后台

    链接:http://pan.baidu.com/s/1c138cwC 密码:9vy9

  9. Feather包实现数据框快速读写,你值得拥有

    什么是Feather? Feature是一种文件格式,支持R语言和Python的交互式存储,速度更快.目前支持R语言的data.frame和Python pandas 的DataFrame. Feat ...

  10. 28 - 生成器交互-__slots__-未实现异常

    目录 1 生成器交互 2 slots 3 未实现和未实现异常 4 Python的对象模型 1 生成器交互 生成器提供了一个send方法用于动态的和生成器对象进行交互.怎么理解的呢?看下面的例子: de ...