bzoj 1814: Ural 1519 Formula 1 插头dp经典题
用的括号序列,听说比较快。
然并不会预处理,只会每回暴力找匹配的括号。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define N 199917 6 #define ll long long 7 #define bp 1<<bit[j-1] 8 #define bq 1<<bit[j] 9 using namespace std; 10 int n,m; 11 int map[15][15]; 12 int head[50006],num,ver[N],nxt[N],tot[2],hash[2][N]; 13 ll f[2][N]; 14 int now,pre; 15 int bit[20]; 16 int edx,edy; 17 bool ed(int x,int y) 18 { 19 return x==edx&&y==edy; 20 } 21 void add(int s,ll d) 22 { 23 int a=s%50000; 24 for(int i=head[a];i;i=nxt[i]) 25 { 26 if(hash[now][ver[i]]==s) 27 { 28 f[now][ver[i]]+=d; 29 return ; 30 } 31 } 32 tot[now]++;hash[now][tot[now]]=s; 33 f[now][tot[now]]=d; 34 num++;nxt[num]=head[a];head[a]=num;ver[num]=tot[now]; 35 return ; 36 } 37 38 int main() 39 { 40 for(int i=1;i<=20;i++)bit[i]=2*i; 41 scanf("%d%d",&n,&m); 42 char s[15]; 43 for(int i=1;i<=n;i++) 44 { 45 scanf("%s",s); 46 for(int j=1;j<=m;j++) 47 { 48 if(s[j-1]=='*')map[i][j]=0; 49 else map[i][j]=1; 50 } 51 } 52 bool flag=0; 53 for(int i=n;i>=1;i--) 54 { 55 for(int j=m;j>=1;j--) 56 { 57 if(map[i][j]) 58 { 59 edx=i,edy=j;break; 60 } 61 } 62 if(edx)break; 63 } 64 now=1;pre=0; 65 f[now][1]=1;tot[now]=1;hash[now][1]=0; 66 for(int i=1;i<=n;i++) 67 { 68 for(int j=1;j<=tot[now];j++)hash[now][j]<<=2; 69 for(int j=1;j<=m;j++) 70 { 71 now^=1;pre^=1; 72 memset(head,0,sizeof(head)); 73 memset(f[now],0,sizeof(f[now])); 74 tot[now]=0;num=0; 75 for(int k=1;k<=tot[pre];k++) 76 { 77 int s=hash[pre][k];ll d=f[pre][k]; 78 if(!d)continue; 79 int p=(s/(bp))&3,q=(s/(bq))&3; 80 if(!map[i][j]) 81 { 82 if(!p&&!q)add(s,d); 83 } 84 else if(!p&&!q) 85 { 86 if(j<m)add(s^(bp)^(bq+1),d); 87 } 88 else if(!p) 89 { 90 if(q==1) 91 { 92 add(s^(bq)^(bp),d); 93 if(j<m)add(s,d); 94 } 95 else 96 { 97 add(s^(bq+1)^(bp+1),d); 98 if(j<m)add(s,d); 99 } 100 } 101 else if(!q) 102 { 103 if(p==1) 104 { 105 if(j<m)add(s^(bp)^(bq),d); 106 add(s,d); 107 } 108 else 109 { 110 if(j<m)add(s^(bq+1)^(bp+1),d); 111 add(s,d); 112 } 113 } 114 else if(p==2) 115 { 116 if(q==1)add(s^(bp+1)^(bq),d); 117 else 118 { 119 int dd=1; 120 for(int l=j-2;l>=0;l--) 121 { 122 if(((s>>bit[l])&3)==2)dd++; 123 else if(((s>>bit[l])&3)==1)dd--; 124 if(!dd) 125 { 126 add((s^(bp+1)^(bq+1))-(1<<bit[l])+(1<<bit[l]+1),d); 127 break; 128 } 129 } 130 } 131 } 132 else if(p==1) 133 { 134 if(q==2) 135 { 136 if(ed(i,j))add(s^(bp)^(bq+1),d); 137 } 138 else 139 { 140 int ss=s>>bit[j+1],dd=1; 141 for(int l=j+1;l<=m;l++,ss>>=2) 142 { 143 if((ss&3)==1)dd++; 144 else if((ss&3)==2)dd--; 145 if(!dd) 146 { 147 add((s^(bp)^(bq))-(1<<bit[l]+1)+(1<<bit[l]),d); 148 break; 149 } 150 } 151 } 152 } 153 } 154 } 155 } 156 ll ans=0; 157 for(int i=1;i<=tot[now];i++) 158 { 159 if(hash[now][ver[i]]==0)ans=f[now][ver[i]]; 160 } 161 printf("%lld\n",ans); 162 return 0; 163 }