# ZOJ 3656 Bit Magic

10 篇文章 0 订阅

Bit Magic，嗯哼？bit，一个int有32bit（废话啦），那和这题什么关系呢？要用数组a[]通过位运算得到矩阵b，似乎很难解~~

 AND 0 1 0 0 0 1 0 1
 OR 0 1 0 0 1 1 1 1
 XOR 0 1 0 0 1 1 1 0

#include<string.h>
#include<algorithm>
#include <cstdio>
using namespace std;

#define MAXN 1010
int n;
unsigned int b[MAXN][MAXN];
int m[MAXN][MAXN];
int id[MAXN];

int find_components(int n,int mat[][MAXN],int* id){
int ret=0,a[MAXN],b[MAXN],c[MAXN],d[MAXN],i,j,k,t;
for (k=0;k<n;id[k++]=0);
for (k=0;k<n;k++)
if (!id[k]){
for (i=0;i<n;i++)
a[i]=b[i]=c[i]=d[i]=0;
a[k]=b[k]=1;
for (t=1;t;)
for (t=i=0;i<n;i++){
if (a[i]&&!c[i])
for (c[i]=t=1,j=0;j<n;j++)
if (mat[i][j]&&!a[j])
a[j]=1;
if (b[i]&&!d[i])
for (d[i]=t=1,j=0;j<n;j++)
if (mat[j][i]&&!b[j])
b[j]=1;
}
for (ret++,i=0;i<n;i++)
if (a[i]&b[i])
id[i]=ret;
}
return ret;
}

void build_map(int k)
{
memset(m, 0, sizeof(m));
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
{
if(i == j) continue;
if(i % 2 == 1 && j % 2 == 1)
{
if((b[i][j] & (1<<k)) )
{
m[i][j+n] = 1;
m[j][i+n] = 1;
}
else
{
m[i+n][i] = 1;
m[j+n][j] = 1;
m[i][j] = m[j][i] = 1;
}
}
else if(i % 2 == 0 && j % 2 == 0)
{
if((b[i][j] & (1<<k)) )
{
m[i][i+n] = 1;
m[j][j+n] = 1;
m[i+n][j+n] = m[j+n][i+n] = 1;
}
else
{
m[j+n][i] = 1;
m[i+n][j] = 1;
}
}
else
{
if((b[i][j] & (1<<k)) )
{
m[i][j+n] = m[j+n][i] = 1;
m[j][i+n] = m[i+n][j] = 1;
}
else
{
m[i][j] = m[j][i] = 1;
m[i+n][j+n] = m[j+n][i+n] = 1;
}
}
}
}

void solve()
{
for(int k = 0; k < 32; k++)
{
build_map(k);
memset(id, 0, sizeof(id));
find_components(2*n, m, id);

/*
printf("%d\n",k);
for (int i=0; i<n; i++,puts(""))
for (int j=0; j<n; j++)
{
printf("%d ",b[i][j]&(1<<k));
}
for(int i = 0; i < n; i++)
{
printf("id[%d] = %d, id[%d] = %d\n", i, id[i], i+n, id[i+n]);
}
*/
for(int i = 0; i < n; i++)
if(id[i] == id[i+n])
{
printf("NO\n");
return;
}
}

printf("YES\n");
}

int main()
{
while(scanf("%d",&n) != EOF)
{
int i, j;
memset(id, 0, sizeof(id));
memset(b, 0, sizeof(b));

for(i = 0; i < n; i++)
for(j = 0; j < n; j++)
scanf("%d",&b[i][j]);

bool flag = true;
for(i = 0; i < n; i++)
if(b[i][i]) { flag = false; break; }

if(flag == false)
{
printf("NO\n");
continue;
}
solve();
}
return 0;
}



• 0
点赞
• 0
评论
• 0
收藏
• 打赏
• 扫一扫，分享海报

10-21 649
10-17 393

10-22 1185
08-11 813
10-29 31
10-01 431
10-01 389
10-15 735
10-14 1865
10-31 600
05-02 870
08-21 1147
08-23 618

zck921031

¥2 ¥4 ¥6 ¥10 ¥20

1.余额是钱包充值的虚拟货币，按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载，可以购买VIP、C币套餐、付费专栏及课程。