FJ省队集训最终测试 T3

思路:状态压缩dp,f[i][j[[k]代表i行j列这个格子,连续的状态为k,这个连续的状态是什么?就是下图

X格子代表我当前走到的地方,而这里的状态就是红色部分,也就是连续的一段n的状态,我们是分每一位计算的,这样就可以转移了,注意,当当前点在最下面的时候要额外计算一个与1的贡献。

坑爹,inf设小了只有30分。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 #define ll long long
 7 const ll inf=1e18;
 8 ll f[50005][41],bin[55],sum[55],ans;
 9 ll a[6][20005],b[6][20005],c1[6][20005],c2[6][20005];
10 ll s[220005];
11 int n,m;
12 ll read(){
13     ll t=0,f=1;char ch=getchar();
14     while (ch<'0'||ch>'9'){if (ch=='-')f=-1;ch=getchar();}
15     while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
16     return t*f;
17 }
18 ll query(int id,int j,int st){
19     int top=0;
20     for (int i=1;i<=n;i++){
21         s[++top]=st%2;
22         st/=2;
23     }
24     s[0]=s[top];s[top+1]=s[1];
25     ll res=0;
26     for (int i=1;i<=n;i++)
27      res+=((s[i]*bin[id])^(a[i][j]&bin[id]))*b[i][j];
28     for (int i=1;i<=n;i++)
29      res+=((s[i]*bin[id])^(bin[id]*s[i+1]))*c2[i][j]; 
30     return res; 
31 }
32 void dp(int id){
33     int tot=(1<<n)-1,cnt=0;
34     for (int i=1;i<=n*m;i++)
35      for (int j=0;j<=tot;j++)
36       f[i][j]=inf;
37     for (int i=0;i<=tot;i++)
38      f[n][i]=query(id,1,i);  
39     for (int j=2;j<=m;j++)
40      for (int i=1;i<=n;i++){
41         int now=(j-1)*n+i,pre=now-1;
42         for (int st=0;st<=tot;st++){
43             int st1=st&sum[n-2],lst=((st&bin[n-2])>0),ths=((st&bin[n-1])>0);
44             ll tmp=0;
45             if (i!=1) tmp+=((lst^ths)*c2[i-1][j])*bin[id];
46             if (i==n) tmp+=(((st&bin[0])^ths)*c2[i][j])*bin[id];
47             tmp+=((a[i][j]&bin[id])^(ths*bin[id]))*b[i][j];
48             for (int k=0;k<=1;k++){
49                 int st2=st1*2+k,beh=((st2&bin[0])>0);
50                 ll tmp2=(beh^ths)*bin[id]*c1[i][j-1];
51                 f[now][st]=std::min(f[now][st],f[pre][st2]+tmp+tmp2);
52             }
53         }
54      }
55      ll Tmp=inf;
56      for (int i=0;i<=tot;i++)
57       Tmp=std::min(f[n*m][i],Tmp);
58      ans+=Tmp; 
59 }
60 int main(){
61     n=read();m=read();bin[0]=1;
62     for (int i=1;i<=19;i++) bin[i]=bin[i-1]*2;sum[0]=bin[0];
63     for (int i=1;i<=19;i++) sum[i]=sum[i-1]+bin[i];
64     for (int i=1;i<=n;i++)
65      for (int j=1;j<=m;j++)
66       a[i][j]=read();
67     for (int i=1;i<=n;i++)
68      for (int j=1;j<=m;j++) 
69       b[i][j]=read();
70     for (int i=1;i<=n;i++)
71      for (int j=1;j<m;j++)
72       c1[i][j]=read();
73     for (int i=1;i<=n;i++)
74      for (int j=1;j<=m;j++)
75       c2[i][j]=read();
76     for (int i=0;i<=19;i++){
77         dp(i);
78     }          
79     printf("%I64d\n",ans);  
80     fclose(stdin);fclose(stdout);
81     return 0;
82 }

 

posted @ 2016-07-09 14:10  GFY  阅读(436)  评论(0编辑  收藏  举报