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

bzoj 4859 ??????[BeiJing2017]机动训练

时间:2018-07-21 17:02:52      阅读:162      评论:0      收藏:0      [点我收藏+]

标签:include   size   方案   sed   set   http   mod   ref   记忆化   

题面

https://www.lydsy.com/JudgeOnline/problem.php?id=4859

题解

和管道取珠类似

首先把平方转化成两条路径经过的图案相同的方案数

对于一条路径 方向一共有8种 分别是 左上 上 右上 左 右 左下 下 右下 (按照起点和终点的位置关系来确定)

我们枚举两个方向 也就是枚举$8 \times 8$ 一共64种方向 注意到对于方向$(a,b)$ 我们发现有其他3种和它是等价的 分别是$(!a,!b),(b,a),(!b,!a)$ (!a 表示a的反方向) 所以实际上只要做$\frac {8 \times 8} {4} =16$种

对于一种情况 我们令$f[a][b][c][d]$表示两条路径的起点分别为$(a,b)$和$(c,d)$的方案数

用记忆化搜索可以算出f数组

然后因为上下左右的四个方向被算了两次 所以得减掉

复杂度$O(16n^4)$

Code

技术分享图片
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4  
 5 ll read(){
 6     ll x=0,f=1;char c=getchar();
 7     while(c<0 || c>9){if(c==-)f=-1;c=getchar();}
 8     while(c>=0 && c<=9){x=x*10+c-0;c=getchar();}
 9     return x*f;
10 }
11  
12 char get(){
13     char c=getchar();
14     while(c!=. && c!=*) c=getchar();
15     return c;
16 }
17  
18 const int mod=1e9+9;
19 int n,m;
20 char s[40][40];
21 int f[33][33][33][33],g[3][3][3][3];
22 int dx[3][3][5]={{{-1,-1,0,0,0},{0,0,0,0,0},{1,1,0,0,0}},{{-1,0,0,0,0},{0,0,0,0,0},{1,0,0,0,0}},{{-1,-1,0,0,0},{0,0,0,0,0},{1,1,0,0,0}}},dy[3][3][5]={{{-1,0,-1,0,0},{-1,0,0,0,0},{-1,0,-1,0,0}},{{0,0,0,0,0},{0,0,0,0,0},{0,0,0,0,0}},{{1,0,1,0,0},{1,0,0,0,0},{1,0,1,0,0}}};
23  
24 inline void pl(int &a,int b){a=a+b;if(a>mod) a-=mod;}
25 inline void dec(int &a,int b){a=a-b;if(a<0) a+=mod;}
26 int q,w,e,r;
27  
28 int dp(int a,int b,int c,int d){
29     //cout<<a<<‘ ‘<<b<<‘ ‘<<c<<‘ ‘<<d<<endl;
30     if(s[a][b]!=s[c][d]) return 0;
31     if(a<1 || a>n || b<1 || b>m || c<1 || c>n || d<1 || d>m) return 0;
32     if(f[a][b][c][d]) return f[a][b][c][d];
33     int sum=1;
34     for(int d1=0;d1<3;d1++){
35         if(dx[q][w][d1]==0 && dy[q][w][d1]==0) continue;
36         int nwa=a+dx[q][w][d1],nwb=b+dy[q][w][d1];
37         for(int d2=0;d2<3;d2++){
38             if(dx[e][r][d2]==0 && dy[e][r][d2]==0) continue;
39             int nwc=c+dx[e][r][d2],nwd=d+dy[e][r][d2];
40             pl(sum,dp(nwa,nwb,nwc,nwd));
41         }
42     }
43     return f[a][b][c][d]=sum;
44 }
45  
46 int solve(int a,int b,int c,int d){
47     if(g[a+1][b+1][c+1][d+1]!=0) return g[a+1][b+1][c+1][d+1];
48     memset(f,0,sizeof(f));
49 //  cout<<a<<‘ ‘<<b<<‘ ‘<<c<<‘ ‘<<d<<endl;
50     q=a+1,w=b+1,e=c+1,r=d+1;
51     int ret=0;
52     for(int i=1;i<=n;i++)
53         for(int j=1;j<=m;j++)
54             for(int x=1;x<=n;x++)
55                 for(int y=1;y<=m;y++)
56                     pl(ret,dp(i,j,x,y));
57     g[a+1][b+1][c+1][d+1]=g[c+1][d+1][a+1][b+1]=g[1-a][1-b][1-c][1-d]=g[1-c][1-d][1-a][1-b]=ret;
58     return ret;
59 }
60  
61 int solve(int a,int b){
62     int ans=0;
63     for(int i=-1;i<=1;i++)
64         for(int j=-1;j<=1;j++){
65             if(i==0 && j==0) continue;
66             if(i==0 || j==0) dec(ans,solve(a,b,i,j));
67             else pl(ans,solve(a,b,i,j));
68         }
69     return ans;
70 }
71  
72 int main(){
73     #ifdef LZT
74     freopen("in","r",stdin);
75     freopen("out2","w",stdout);
76     #endif
77     n=read(),m=read();
78     for(int i=1;i<=n;i++)
79         scanf("%s",s[i]+1);
80     int ans=0;
81     for(int i=-1;i<=1;i++)
82         for(int j=-1;j<=1;j++){
83             if(i==0 && j==0) continue;
84             if(i==0 || j==0) dec(ans,solve(i,j));
85             else pl(ans,solve(i,j));
86         }
87     printf("%d\n",ans);
88     return 0;
89 }
View Code

Review

1. 注意模数为$10^9+9$ 我一开始写成了$10^9+7$调了半天

 

bzoj 4859 ??????[BeiJing2017]机动训练

标签:include   size   方案   sed   set   http   mod   ref   记忆化   

原文地址:https://www.cnblogs.com/wawawa8/p/9346404.html

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