您的位置:首页 > 其它

TJOI2015 棋盘

2015-05-04 10:26 176 查看

Description



Input



Output



Sample Input

2 2
3 1
0 1 0
1 1 1
0 1 0


Sample Output

7


Data Constraint



这题有个巨坑的地方,棋子在第1行,每k列,行和列都是从0开始编号的!!!也就是实际是第2行,第k+1列!!!

看出来后就一大水题了。

经过转换可以使得每个棋子都只影响下一行,又由于列只有6,所以用状压解

f[i][[j]表示每i行状态为j的方案,然后我们发现每2行之间的转移是一样的,所以可以预处理转移矩阵,再矩乘加快速幂优化即可

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
using namespace std;
typedef unsigned int ui;

vector<int> lim[4];

struct Matrix{
ui a[65][65];
}pc,d;

ui ans;
ui f[1011];
int i,j,k,p,m,nj,l,n,L,sy;
int a[4][10];

Matrix operator *(Matrix a,Matrix b)
{
Matrix c;
memset(c.a,0,sizeof(c.a));
int i,j,k;
for(i=0;i<(1<<m);i++)
for(k=0;k<(1<<m);k++)if(a.a[i][k]){
for(j=0;j<(1<<m);j++)c.a[i][j]+=a.a[i][k]*b.a[k][j];
}
return c;
}

Matrix mi(Matrix a,int z)
{
Matrix l;
bool pz;
int i,j;
pz=true;
while(z){
if(z%2==1){
if(pz){
pz=false;
for(i=0;i<(1<<m);i++)
for(j=0;j<(1<<m);j++)l.a[i][j]=a.a[i][j];
}
else l=l*a;
}
a=a*a;
z/=2;
}
return l;
}

bool check(int ls,int ts)
{
int i,j,sy,k;
for(i=0;i<m;i++)if((ls&(1<<i))){
for(j=0;j<lim[3].size();j++){
k=lim[3][j];
sy=i+1+k-L;
if(sy>0&&sy<=m){
if((ts&(1<<(sy-1))))return false;
}
}
}
for(i=0;i<m;i++)if((ts&(1<<i))){
for(j=0;j<lim[2].size();j++){
k=lim[2][j];
sy=i+1+k-L;
if(sy>0&&sy<=m){
if(sy!=i+1&&(ts&(1<<(sy-1))))return false;
}
}
}
return true;
}

int main()
{
scanf("%d%d",&n,&m);
scanf("%d%d",&p,&L);
L++;
for(i=1;i<=3;i++)
for(j=1;j<=p;j++){
scanf("%d",&a[i][j]);
if(a[2][j])lim[2].push_back(j);
if(a[3][j])lim[3].push_back(j);
}
for(i=1;i<=p;i++)if(a[1][i]){
sy=L+L-i;
lim[3].push_back(sy);
}
for(i=0;i<(1<<m);i++)
for(j=0;j<(1<<m);j++)if(check(i,j))pc.a[i][j]=1;
d=mi(pc,n);
for(i=0;i<(1<<m);i++)if(pc.a[0][i])f[i]++;
for(i=0;i<(1<<m);i++)ans+=f[i]*d.a[i][0];
printf("%u\n",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: