思路:状态压缩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 }
时间: 2024-10-03 18:24:39