BZOJ4676: Xor-Mul棋盘
2016-08-12 10:27
162 查看
题目大意:给定一个网格棋盘,每条边有一个权值c,每个点有两个权值a,b,你需要给每个点一个权值d,使得每个点的(a^d)*c的和+每条边的两个端点的d异或起来*c的和最小
首先因为是位运算,所以每一位相互独立,可以分开算
然后就能想到状压DP,因为n只有5而且每一列只和上一列有关系,所以可以设f[i][j]表示第i列的状态为j,目前产生的代价最小值
这样转移的时候枚举上一列的情况,然后计算新产生的权值,时间复杂度是O(位运算的每一位*m*状态数*上一列的状态数*计算对应的权值)=O(20*M*2^n*2^n*n)=O(20NM*4^n)
显然是过不了的
我们考虑优化,我们可以发现计算新的权值这一步挪到外面去做,因为他跟你是哪一位没关系,只需要O(M*4^n)预处理出对于每一列来说这列状态和上一列状态分别是j和k时边产生的代价,再O(NM*2^n)当这一列状态为j时,点产生的代价,这样在枚举每一位时就不需要O(N)计算新产生的权值了!
总时间复杂度降成了O(20M*4^N)
#pragma GCC optimize("O2")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 10010
using namespace std;
long long n,m;
long long a[6]
,b[6]
,c1[6]
,c2[6]
;
long long A[6]
;
long long f
[32],F
[32][32];
bool p(long long x,long long k)
{
return ((x&(1<<(k-1)))!=0);
}
long long solve(long long x)
{
long long i,j,k,l;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
if(a[i][j]&x) A[i][j]=1;
else A[i][j]=0;
}
for(i=1;i<=m;i++)
for(k=0;k<(1<<n);k++)
{
long long tmp=0;
for(j=1;j<=n;j++)
{
tmp+=b[j][i]*(A[j][i]^p(k,j));
if(j==n)
tmp+=c2[j][i]*(p(k,n)^p(k,1));
else
tmp+=c2[j][i]*(p(k,j)^p(k,j+1));
}
f[i][k]=1e18;
//if(k==3) cout<<tmp;
for(l=0;l<(1<<n);l++)
{
long long tmp2=0;
f[i][k]=min(f[i][k],f[i-1][l]+F[i][k][l]);
}
f[i][k]+=tmp;
/* if(k==3)
cout<<i<<' '<<k<<' '<<f[i][k]<<endl;*/
}
long long minn=1e18;
for(i=0;i<(1<<n);i++)
minn=min(minn,f[m][i]);
return minn*x;
}
int main()
{
scanf("%lld%lld",&n,&m);
long long i,j,k,l;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
scanf("%lld",&a[i][j]);
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
scanf("%lld",&b[i][j]);
for(i=1;i<=n;i++)
for(j=1;j<m;j++)
scanf("%lld",&c1[i][j]);
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
scanf("%lld",&c2[i][j]);
for(i=1;i<=m;i++)
for(k=0;k<(1<<n);k++)
{
long long tmp=0;
for(l=0;l<(1<<n);l++)
{
long long tmp2=0;
for(j=1;j<=n;j++)
tmp2+=c1[j][i-1]*(p(k,j)^p(l,j));
F[i][k][l]=tmp2;
}
}
long long ans=0;
for(i=0;i<=19;i++)
ans+=solve(1<<i);
printf("%lld",ans);
}
首先因为是位运算,所以每一位相互独立,可以分开算
然后就能想到状压DP,因为n只有5而且每一列只和上一列有关系,所以可以设f[i][j]表示第i列的状态为j,目前产生的代价最小值
这样转移的时候枚举上一列的情况,然后计算新产生的权值,时间复杂度是O(位运算的每一位*m*状态数*上一列的状态数*计算对应的权值)=O(20*M*2^n*2^n*n)=O(20NM*4^n)
显然是过不了的
我们考虑优化,我们可以发现计算新的权值这一步挪到外面去做,因为他跟你是哪一位没关系,只需要O(M*4^n)预处理出对于每一列来说这列状态和上一列状态分别是j和k时边产生的代价,再O(NM*2^n)当这一列状态为j时,点产生的代价,这样在枚举每一位时就不需要O(N)计算新产生的权值了!
总时间复杂度降成了O(20M*4^N)
#pragma GCC optimize("O2")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 10010
using namespace std;
long long n,m;
long long a[6]
,b[6]
,c1[6]
,c2[6]
;
long long A[6]
;
long long f
[32],F
[32][32];
bool p(long long x,long long k)
{
return ((x&(1<<(k-1)))!=0);
}
long long solve(long long x)
{
long long i,j,k,l;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
if(a[i][j]&x) A[i][j]=1;
else A[i][j]=0;
}
for(i=1;i<=m;i++)
for(k=0;k<(1<<n);k++)
{
long long tmp=0;
for(j=1;j<=n;j++)
{
tmp+=b[j][i]*(A[j][i]^p(k,j));
if(j==n)
tmp+=c2[j][i]*(p(k,n)^p(k,1));
else
tmp+=c2[j][i]*(p(k,j)^p(k,j+1));
}
f[i][k]=1e18;
//if(k==3) cout<<tmp;
for(l=0;l<(1<<n);l++)
{
long long tmp2=0;
f[i][k]=min(f[i][k],f[i-1][l]+F[i][k][l]);
}
f[i][k]+=tmp;
/* if(k==3)
cout<<i<<' '<<k<<' '<<f[i][k]<<endl;*/
}
long long minn=1e18;
for(i=0;i<(1<<n);i++)
minn=min(minn,f[m][i]);
return minn*x;
}
int main()
{
scanf("%lld%lld",&n,&m);
long long i,j,k,l;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
scanf("%lld",&a[i][j]);
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
scanf("%lld",&b[i][j]);
for(i=1;i<=n;i++)
for(j=1;j<m;j++)
scanf("%lld",&c1[i][j]);
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
scanf("%lld",&c2[i][j]);
for(i=1;i<=m;i++)
for(k=0;k<(1<<n);k++)
{
long long tmp=0;
for(l=0;l<(1<<n);l++)
{
long long tmp2=0;
for(j=1;j<=n;j++)
tmp2+=c1[j][i-1]*(p(k,j)^p(l,j));
F[i][k][l]=tmp2;
}
}
long long ans=0;
for(i=0;i<=19;i++)
ans+=solve(1<<i);
printf("%lld",ans);
}
相关文章推荐
- 【BZOJ4676】Xor-Mul棋盘 拆位+状压DP
- BZOJ4676 Xor-Mul棋盘/BZOJ3254 Xor-Mul Chessboard
- BZOJ-2115-Xor-WC2011
- BZOJ 4813 [Cqoi2017]小Q的棋盘
- bzoj 4269: 再见Xor (高斯消元求解线性基)
- [BZOJ2337] [HNOI2011] XOR和路径 期望 + 按位处理 + 高斯消元
- 【BZOJ 2115】【WC 2011】Xor
- BZOJ1457 棋盘游戏
- 洛谷 P1169 [ZJOI2007]棋盘制作(bzoj P1057 [ZJOI2007]棋盘制作)
- [BZOJ 1057][ZJOI 2007]棋盘制作(最大全0/1子矩阵)
- bzoj 4245: [ONTAK2015]OR-XOR
- 【概率DP/高斯消元】BZOJ 2337:[HNOI2011]XOR和路径
- [BZOJ1954]Pku3764 The xor-longest Path
- BZOJ 4245: [ONTAK2015]OR-XOR
- [BZOJ1453][Wc]Dface双面棋盘(lct)
- BZOJ 3106: [cqoi2013]棋盘游戏
- 【博弈论】【SG函数】bzoj1457 棋盘游戏
- BZOJ 4245 OR-XOR
- BZOJ 4269 再见Xor 高斯消元
- bzoj 4245: [ONTAK2015]OR-XOR