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. matlab图像

    1.在网络上发现matlab能画出一些很有意思的图形(立体爱心) clc; const=0; x=-5:0.05:5;y=-5:0.05:5;z=-5:0.05:5; [x,y,z]=meshgrid ...

  2. nodejs express框架一个工程中同时使用ejs模版和jade模版

    在某些项目中,比如你接手了一个别人的项目然后你不想用蛋疼的ejs,或者你不想用蛋疼的jade.你有不想重写之前的页面,那么你现在可能需要新引入ejs或者jade模块,你仅仅需要做下面两步也许就能完成使 ...

  3. phpmyadmin 登录时间修改

    登录后1440秒未活动后总是自动退出,一天还要登录多次,终于有时间来解决这个问题了,感觉是session超时,结果在网上search了下,找到解决办法啦,哈哈哈,在此做个笔记:phpmyadmin在使 ...

  4. Scratch编程小案例:愤怒的小牛

    愤怒的小鸟曾经很热门,网上还说他是程序员最喜欢玩的游戏.最先我是WIKIOI的评测页面看到他的,后来在2014年全国信息学奥林匹克联赛第一天第三题飞扬的小鸟也看到了它.因此,突然想做一个类似愤怒的小鸟 ...

  5. jeecms上传文件限制导致413-Request Entity Too Large

    1:spring mvc 上传限制大小  配置是否允许在上传文件的大小 <bean id="multipartResolver" class="org.spring ...

  6. KMP next表模板

    void makeNext(const char P[],int next[]) { int q,k;//q:模版字符串下标:k:最大前后缀长度 int m = strlen(P);//模版字符串长度 ...

  7. Python学习笔记(三十九)— 内置模块(8)XML基础

    摘抄自:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001432002075 ...

  8. 关于变长数组的一点小想法-C语言定义数组但是数组长度不确定怎么办

    很多数据机构,比如栈,链表等,都可以动态分配存储空间 那么数组呢?一般声明时都要指定数组长度,那么数组可以实现动态分配么? 假设数组存的是int型 那么 你先申请10个元素 int* a = (int ...

  9. 【CodeForces】578 C. Weakness and Poorness

    [题目]C. Weakness and Poorness [题意]给定含n个整数的序列ai,定义新序列为ai-x,要使新序列的最大子段和绝对值最小,求实数x.n<=2*10^5. [算法]二分| ...

  10. 关于HttpWebRequest发生服务器协议冲突的解决办法

    WinForm下的app.config文件中添加: <system.net>    <settings>      <httpWebRequest useUnsafeHe ...