• 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
    ",ans);  
    80     fclose(stdin);fclose(stdout);
    81     return 0;
    82 }
  • 相关阅读:
    c++计算器后续(1)
    第七次作业
    第六次作业之计算器图形界面(之骗分)
    C++课堂作业二之反转链表
    第五次作业(计算器第三步之文件输入输出)
    ARP详解和ARP攻击
    网络基础-端口
    网络基础-子网掩码
    Informatica ODBC的使用
    linux7 grub配置文件 linux6 grub配置文件
  • 原文地址:https://www.cnblogs.com/qzqzgfy/p/5655801.html
Copyright © 2020-2023  润新知