码迷,mamicode.com
首页 > 其他好文 > 详细

【Ural】【1519】Formula 1

时间:2015-03-04 00:56:17      阅读:163      评论:0      收藏:0      [点我收藏+]

标签:

插头DP


本题为CDQ《基于连通性状态压缩的动态规划的……(我忘了)》里的例题!(嗯就是这样……)

先膜拜一下ccy大神……http://blog.sina.com.cn/s/blog_51cea4040100gmky.html

 

在这里将我当初看插头DP的一些不解之处写出来,给大家提供一些参考:

  以前我老是搞不懂“左/右插头”的区分……今天终于搞明白了:左插头是一个联通块与轮廓线的左边的交点,右插头是靠右的交点……这下那些分情况讨论的状态转移瞬间就明白了= =

  然后是状态表示……其实以前用状压都是一位表示一个状态,而插头DP由于用的是3(4)进制,所以是二进制下的两位来表示一个插头的状态(两位的话就可以表示0/1/2了,一位只能表示0/1)

  状态转移其实就是删掉/加上插头的操作……看了代码很好懂……sigh……当年是一看长代码就头晕,唉

  其实我们是在对每一个格子枚举可行状态的……要不然怎么叫统计方案数啊= =(这一点我一开始真的没想到……so sad……too naive)

  其实在看插头DP代码的过程中也顺便理解了Hash……原来hash向后排是这个意思,开个数组记录下每个hash值所对应的原值就好了,好像也没那么难的样子……为什么当初我NOIP的时候就没学会呢……

技术分享
  1 //Ural 1519
  2 #include<cmath>
  3 #include<vector>
  4 #include<cstdio>
  5 #include<cstring>
  6 #include<cstdlib>
  7 #include<iostream>
  8 #include<algorithm>
  9 #define rep(i,n) for(int i=0;i<n;++i)
 10 #define F(i,j,n) for(int i=j;i<=n;++i)
 11 #define D(i,j,n) for(int i=j;i>=n;--i)
 12 #define CC(a,b) memset(a,b,sizeof(a))
 13 #define pb push_back
 14 using namespace std;
 15 int getint(){
 16     int v=0,sign=1; char ch=getchar();
 17     while(ch<0||ch>9){ if (ch==-) sign=-1; ch=getchar();}
 18     while(ch>=0&&ch<=9){ v=v*10+ch-0; ch=getchar();}
 19     return v*=sign;
 20 }
 21 const int N=1e7+10;
 22 typedef long long LL;
 23 typedef unsigned long long u64;
 24 /******************tamplate*********************/
 25 const int sz=199917;
 26 bool mp[15][15];
 27 int n,m,nn,mm,k;
 28 int tot[2],bit[15],hash[sz],state[2][sz];
 29 u64 dp[2][sz],ans;
 30 void init(){
 31     CC(mp,0);
 32     CC(dp,0);
 33     tot[0]=dp[0][1]=1,ans=k=0;
 34     state[0][1]=0;
 35     char ch;
 36     F(i,1,n){
 37         scanf("%c",&ch);
 38         F(j,1,m){
 39             scanf("%c",&ch);
 40             mp[i][j]=ch==.;
 41             if (mp[i][j]) nn=i,mm=j;
 42         }
 43     }
 44 }
 45 void hash_in(int s,u64 sum){
 46     int p=s%sz;
 47     while(hash[p]){
 48         if (state[k][hash[p]]==s){
 49             dp[k][hash[p]]+=sum;
 50             return;
 51         }
 52         p++;
 53         if (p==sz) p=0;
 54     }
 55     hash[p]=++tot[k];
 56     state[k][hash[p]]=s;
 57     dp[k][hash[p]]=sum;
 58 }
 59 #define in hash_in(s,sum)
 60 void work(){
 61     F(i,1,n){
 62         F(j,1,m){
 63             k^=1;
 64             tot[k]=0;
 65             CC(hash,0);
 66             F(u,1,tot[1-k]){
 67                 int s=state[1-k][u];
 68                 u64 sum=dp[1-k][u];
 69                 int p=(s>>bit[j-1])&3,q=(s>>bit[j])&3;
 70                 if (!mp[i][j]){ if(!p && !q) in; }
 71                 else{
 72                     if (!p && !q){
 73                         if (!mp[i][j+1]||!mp[i+1][j]) continue;
 74                         s=s^(1<<bit[j-1])^(1<<bit[j]<<1),in;
 75                     }else if(!p && q){
 76                         if (mp[i][j+1]) in;
 77                         if (mp[i+1][j]) s=s^q*(1<<bit[j-1])^q*(1<<bit[j]),in;
 78                     }else if(p && !q){
 79                         if (mp[i+1][j]) in;
 80                         if (mp[i][j+1]) s=s^p*(1<<bit[j-1])^p*(1<<bit[j]),in;
 81                     }else if(p+q==2){
 82                         int nd=1;
 83                         F(u,j+1,m){
 84                             int w=(s>>bit[u])&3;
 85                             if (w==1) nd++;
 86                             if (w==2) nd--;
 87                             if (!nd) {s-=(1<<bit[u]); break;}//这两个地方不能将+/-改成^
 88                             //废话!因为这里是把右插头(2)改成左插头(1)了!用异或就把2改成3了……那算神马……
 89                         }
 90                         s=s^(1<<bit[j])^(1<<bit[j-1]),in;
 91                     }else if(p+q==4){
 92                         int nd=1;
 93                         D(u,j-2,1){
 94                             int w=(s>>bit[u])&3;
 95                             if (w==2) nd++;
 96                             if (w==1) nd--;
 97                             if (!nd) {s+=(1<<bit[u]); break;}//这里是将左插头(1)改成右插头(2)
 98                         }
 99                         s=s^(1<<bit[j]<<1)^(1<<bit[j-1]<<1),in;
100                     }else if(p==1 && q==2){
101                         if (i==nn && j==mm) ans+=sum;
102                     }else if(p==2 && q==1) s=s^(1<<bit[j-1]<<1)^(1<<bit[j]),in;
103                 }
104             }
105         }
106         F(j,1,tot[k]) state[k][j]<<=2;
107     }
108     printf("%llu\n",ans);
109 }
110 
111 int main(){
112 #ifndef ONLINE_JUDGE
113     freopen("1519.in","r",stdin);
114     freopen("1519.out","w",stdout);
115 #endif
116     F(i,0,13) bit[i]=i<<1;
117     while(scanf("%d%d",&n,&m)!=EOF){
118         init();
119         work();
120     }
121     return 0;
122 }
View Code

 

【Ural】【1519】Formula 1

标签:

原文地址:http://www.cnblogs.com/Tunix/p/4312203.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!