hdu4796

Posted phile的空间

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu4796相关的知识,希望对你有一定的参考价值。

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

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

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

1.怎么处理独立插头

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

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

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

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

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

技术分享
  1 #include<bits/stdc++.h>
  2 
  3 using namespace std;
  4 typedef long long ll;
  5 const int mo=30007;
  6 const int maxl=2000010;
  7 char s[30];
  8 int n,m,ans,en,p,a[30][30],v[15],b[15],c[15];
  9 
 10 struct node{
 11     int p[mo],nex[maxl],len,f[maxl];
 12     ll st[maxl];
 13     void clr()
 14     {
 15         len=0; memset(p,255,sizeof(p));
 16     }
 17     void push(ll nw,int s)
 18     {
 19         int x=nw%mo;
 20         for (int i=p[x];i!=-1; i=nex[i])
 21             if (st[i]==nw)
 22             {
 23                 f[i]=min(f[i],s);
 24                 return;
 25             }
 26         st[++len]=nw; f[len]=s;
 27         nex[len]=p[x]; p[x]=len;
 28     }
 29 } h[2];
 30 
 31 void get(ll st)
 32 {
 33     for (int i=m; i>=0; i--)
 34     {
 35         c[i]=st&7;
 36         st>>=3;
 37     }
 38 }
 39 
 40 ll put()
 41 {
 42     memset(v,255,sizeof(v)); v[0]=0;
 43     ll st=0; int t=0;
 44     for (int i=0; i<=m; i++)
 45     {
 46         if (v[b[i]]==-1) v[b[i]]=++t;
 47         b[i]=v[b[i]];
 48         st<<=3; st|=b[i];
 49     }
 50     return st;
 51 }
 52 
 53 void shift()
 54 {
 55     for (int i=m;i; i--) b[i]=b[i-1];
 56     b[0]=0;
 57 }
 58 
 59 int check(int j)
 60 {
 61     int f=0;
 62     for (int i=0; i<=j; i++)
 63         f+=(c[i]>0);
 64     return f;
 65 }
 66 
 67 void dp(int i,int j)
 68 {
 69     for (int k=1; k<=h[p^1].len; k++)
 70     {
 71         ll st=h[p^1].st[k];
 72         get(st); int pw=h[p^1].f[k];
 73         int x=c[j-1],y=c[j];
 74         memcpy(b,c,sizeof(b));
 75         if (a[i][j]>=0)
 76         {
 77             if (x&&y)
 78             {
 79                 if (x==y) continue;
 80                 b[j-1]=b[j]=0;
 81                 for (int r=0; r<=m; r++)
 82                     if (b[r]==x) b[r]=y;
 83                 if (j==m) shift();
 84                 h[p].push(put(),pw+a[i][j]);
 85                 continue;
 86             }
 87             else if (x||y)
 88             {
 89                 int r=x+y;
 90                 if (a[i][j+1]>=0)
 91                 {
 92                     b[j]=r; b[j-1]=0;
 93                     h[p].push(put(),pw+a[i][j]);
 94                 }
 95                 if (a[i+1][j]>=0||(i==n&&!check(j-2)))
 96                 {
 97                     b[j]=0; b[j-1]=r;
 98                     if (j==m) shift();
 99                     h[p].push(put(),pw+a[i][j]);
100                 }
101             }
102             else {
103                 if (a[i][j+1]>=0&&(a[i+1][j]>=0||(i==n&&!check(j-2))))
104                 {
105                     b[j]=b[j-1]=m+1;
106                     h[p].push(put(),pw+a[i][j]);
107                 }
108                 b[j]=b[j-1]=0;
109                 if (j==m) shift();
110                 h[p].push(put(),pw);
111             }
112         }
113         else {
114             if (a[i][j]==-1)
115             {
116                 if (j==m) shift();
117                 h[p].push(put(),pw);
118                 continue;
119             }
120             int sd=check(j-2);
121             if (!(sd&1)&&a[i][j]==-3) continue;
122             if (sd&1&&a[i][j]==-2) continue;
123             if (j==m) shift();
124             h[p].push(put(),pw);
125         }
126     }
127 }
128 
129 int main()
130 {
131     //freopen("1.in","r",stdin);
132     //freopen("1.out","w",stdout);
133     while (scanf("%d%d",&n,&m)!=EOF)
134     {
135         memset(a,255,sizeof(a));
136         for (int i=1; i<=n; i++)
137         {
138             scanf("%s",s+1);
139             for (int j=1; j<=m; j++)
140             {
141                 int x=-1;
142                 if (s[j]==#) x=-1;
143                 else if (s[j]==W) x=-2;
144                 else if (s[j]==L) x=-3;
145                 else x=s[j]-0;
146                 a[i][j]=x;
147             }
148         }
149         ans=1e9+7;
150         h[1].clr(); h[0].clr(); p=0;
151         for (int i=1; i<=m; i++)
152             if (a[1][i]>=0)
153             {
154                 memset(b,0,sizeof(b)); b[i]=1;
155                 h[0].push(put(),0);
156             }
157         for (int i=1; i<=n; i++)
158             for (int j=1; j<=m; j++)
159             {
160                 p^=1; h[p].clr();
161                 dp(i,j);
162               //  cout <<h[p].len<<" "<<i<<" "<<j<<endl;
163             }
164         for (int k=1; k<=h[p].len; k++)
165         {
166             get(h[p].st[k]);
167             int sd=check(m);
168             if (sd==1) ans=min(ans,h[p].f[k]);
169         }
170         if (ans==1000000007) puts("-1"); else printf("%d\n",ans);
171     }
172 }
View Code

 

以上是关于hdu4796的主要内容,如果未能解决你的问题,请参考以下文章

dpluoguP4796 关于图 想不到是状压dp (┬_┬)

HDU4057 Rescue the Rabbit(AC自动机+状压DP)

HDU3247 Resource Archiver(AC自动机+BFS+DP)

POJ - 2778 ~ HDU - 2243 AC自动机+矩阵快速幂

微信小程序代码片段

VSCode自定义代码片段——CSS选择器