hdu4796
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的更多相关文章
随机推荐
- DevExpress Components16.2.6 Source Code 重编译教程
DevExpress 是一个比较有名的界面控件套件,提供了一系列优秀的界面控件.这篇文章将展示如何在拥有源代码的情况下,对 DevExpress 的程序集进行重新编译. 特别提示:重编译后,已安装好的 ...
- python学习(八)定制类和枚举
`python`定制类主要是实现特定功能,通过在类中定义特定的函数完成特定的功能. class Student(object): def __init__(self, name): self.name ...
- STL源码分析-rbtree
http://note.youdao.com/noteshare?id=4f8d16e565478b4e98bf2e56ce98a28e
- wx.request 获取不到post传递的值
微信小程序的wx.request请求,method设为POST并向后台传递数据,但从后台返回的信息来看后台并没有获得传递的数据 wx.request({ url: 'url' ...
- duilib 修复CTreeViewUI复选功能判断不准确的bug
转载请说明出处,谢谢~~:http://blog.csdn.net/zhuhongshu/article/details/42265209 CTreeViewUI里面自带了复选的功能,但是复选功能存在 ...
- 笔记(二)TabLayout + ViewPager + FragmentPagerAdapter 组合用法
TabLayout的xml文件 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" ...
- [Luogu 2486] SDOI2011 染色
[Luogu 2486] SDOI2011 染色 树剖水题,线段树维护. 详细题解不写了. 我只想说我写的线段树又变漂亮了qwq #include <algorithm> #include ...
- 使用itextpdf提取pdf内容
package test; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList ...
- ① 设计模式的艺术-01.单例(Singleton)模式
单例模式为何要出现 在工作过程中,发现所有可以使用单例模式的类都有一个共性,那就是这个类没有自己的状态,换句话说,这些类无论你实例化多少个,其实都是一样的. 如果我们不将这个类控制成单例的结构,应用中 ...
- Dubbo+Zookeeper+SpringMVC+Maven整合实现微服务项目
互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,Dubbo是一个分布式服务框架,在这种情况下诞生的.现在核心业务抽取出来,作为独立的服务,使 ...