zoukankan      html  css  js  c++  java
  • CF1205C Palindromic Paths

    题目链接

    问题分析

    首先可以想到,坐标和为奇数的位置可以被唯一确定。同样的,如果假定((1,2))(0),那么坐标和为偶数的位置也可以被唯一确定。这样总共使用了(n^2-3)次询问。

    那么接下来就需要在(3)步之内判断是否要翻转坐标和为偶数的位置。

    如果仅仅只是这样简单的判断:

    printf( "? 1 1 2 3
    " ); fflush( stdout );
    	int x; scanf( "%d", &x );
    	if( x == 1 && A[ 1 ][ 1 ] != A[ 2 ][ 3 ] ) 
    		for( int i = 1; i <= n; ++i )
    			for( int j = 1; j <= n; ++j ) 
    				if( ( i + j ) % 2 )
    					A[ i ][ j ] = ( A[ i ][ j ] == 1 ) ? 0 : 1;
    	if( x == 0 && A[ 1 ][ 1 ] == A[ 2 ][ 3 ] && 
    		( A[ 2 ][ 1 ] == A[ 2 ][ 2 ] || A[ 1 ][ 2 ] == A[ 2 ][ 2 ] || A[ 1 ][ 2 ] == A[ 1 ][ 3 ] ) )
    		for( int i = 1; i <= n; ++i )
    			for( int j = 1; j <= n; ++ j )
    				if( ( i + j ) % 2 )
    					A[ i ][ j ] = ( A[ i ][ j ] == 1 ) ? 0 : 1;
    

    那么就愉快的Wrong Answer on test 5

    观察这样一组数据:

    110
    101
    110
    

    会发现,不论是否翻转,所得的结果都是(0)

    观察发现,翻转会改变这样一条长度为(4)的路径上的两个位置。而这样路径上值的异或和是不变的。而长度为(4)(01)串异或和为(0)是回文的必要条件。如果异或和不为(0),就会出现所给反例中的情况。

    那么异或和为(0)的长度为(4)的路径是否一定存在?考虑反证法。

    假设不存在这样一条路径。考虑从左上到右下的任意一条路径。这条路径的长度为(2n-1)。不妨设这条路径所组成的序列是({a_i})。那么(a_1 oplus a_2 oplus a_3 oplus a_4=1)(a_2oplus a_3oplus a_4oplus a_5=1)。那么(a_1=a_5)。同样的(a_i=a_{i-4})。由于(n)是奇数,所以(a_{2n-1}=a_1)。 而题目中要求(a_1=1,a_{2n-1}=0),所以一定存在这样一条路径。

    那么就得到了可行的做法。

    参考程序

    #include <bits/stdc++.h>
    using namespace std;
    
    const int Maxn = 60;
    int n, A[ Maxn ][ Maxn ], x;
    
    int Check( int x1, int y1, int x2, int y2 ) {
    	if( x1 == x2 ) return 1 ^ A[ x1 ][ y1 ] ^ A[ x1 ][ y1 + 1 ] ^ A[ x1 ][ y1 + 2 ] ^ A[ x1 ][ y2 ];
    	if( x1 + 1 == x2 ) {
    		int t = A[ x1 ][ y1 ] ^ A[ x2 ][ y2 ];
    		return ( t == ( A[ x1 + 1 ][ y1 ] ^ A[ x1 + 1 ][ y1 + 1 ] ) ) || 
    			( t == ( A[ x1 ][ y1 + 1 ] ^ A[ x1 + 1 ][ y1 + 1 ] ) ) ||
    			( t == ( A[ x1 ][ y1 + 1 ] ^ A[ x1 ][ y1 + 2 ] ) );
    	}
    	if( x1 + 2 == x2 ) {
    		int t = A[ x1 ][ y1 ] ^ A[ x2 ][ y2 ];
    		return ( t == ( A[ x1 + 1 ][ y1 ] ^ A[ x1 + 2 ][ y1 ] ) ) || 
    			( t == ( A[ x1 + 1 ][ y1 ] ^ A[ x1 + 1 ][ y1 + 1 ] ) ) ||
    			( t == ( A[ x1 ][ y1 + 1 ] ^ A[ x1 + 1 ][ y1 + 1 ] ) );
    	}
    	if( x1 + 3 == x2 ) return 1 ^ A[ x1 ][ y1 ] ^ A[ x1 + 1 ][ y1 ] ^ A[ x1 + 2 ][ y1 ] ^ A[ x2 ][ y1 ];
    	return 0;
    }
    
    void Swap() {
    	for( int i = 1; i <= n; ++i )
    		for( int j = 1; j <= n; ++j ) 
    			if( ( i + j ) % 2 )
    				A[ i ][ j ] = ( A[ i ][ j ] == 1 ) ? 0 : 1;
    	return;
    }
    
    void Trans() {
    	for( int i = 1; i <= n; ++i ) 
    		for( int j = 1; j <= n; ++j )
    			for( int k = 0; k < 4; ++k )
    				if( i + k <= n && j + 3 - k <= n && Check( i, j, i + k, j + 3 - k ) ) {
    					printf( "? %d %d %d %d
    ", i, j, i + k, j + 3 - k ); fflush( stdout ); scanf( "%d", &x );
    					if( x == 1 && A[ i ][ j ] != A[ i + k ][ j + 3 - k ] ) Swap();
    					if( x == 0 && A[ i ][ j ] == A[ i + k ][ j + 3 - k ] ) Swap();
    					return;
    				}
    	return;
    }
    
    int main() {
    	memset( A, 0, sizeof( A ) );
    	A[ 1 ][ 1 ] = 1;
    	scanf( "%d", &n );
    	for( int i = 1; i <= n; ++i ) 
    		for( int j = 1; j <= n; ++j ) {
    			if( i == 2 && j == 1 ) {
    				printf( "? 2 1 2 3
    " ); fflush( stdout ); scanf( "%d", &x );
    				if( x == 0 ) A[ 2 ][ 1 ] = ( A[ 2 ][ 3 ] == 1 ) ? 0 : 1;
    				if( x == 1 ) A[ 2 ][ 1 ] = ( A[ 2 ][ 3 ] == 1 ) ? 1 : 0;
    			}
    			if( i == 1 && j + 2 <= n ) {
    				printf( "? %d %d %d %d
    ", i, j, i, j + 2 ); fflush( stdout ); scanf( "%d", &x );
    				if( x == 0 ) A[ i ][ j + 2 ] = ( A[ i ][ j ] == 1 ) ? 0 : 1;
    				if( x == 1 ) A[ i ][ j + 2 ] = ( A[ i ][ j ] == 1 ) ? 1 : 0;
    			}
    			if( j == 1 && i + 2 <= n ) {
    				printf( "? %d %d %d %d
    ", i, j, i + 2, j ); fflush( stdout ); scanf( "%d", &x );
    				if( x == 0 ) A[ i + 2 ][ j ] = ( A[ i ][ j ] == 1 ) ? 0 : 1;
    				if( x == 1 ) A[ i + 2 ][ j ] = ( A[ i ][ j ] == 1 ) ? 1 : 0;
    			}
    			if( i + 1 <= n && j + 1 <= n && i + j + 2 < n + n ) {
    				printf( "? %d %d %d %d
    ", i, j, i + 1, j + 1 ); fflush( stdout ); scanf( "%d", &x );
    				if( x == 0 ) A[ i + 1 ][ j + 1 ] = ( A[ i ][ j ] == 1 ) ? 0 : 1;
    				if( x == 1 ) A[ i + 1 ][ j + 1 ] = ( A[ i ][ j ] == 1 ) ? 1 : 0;
    			}
    		}
    	Trans();
    	printf( "!
    " ); fflush( stdout );
    	for( int i = 1; i <= n; ++i ) {
    		for( int j = 1; j <= n; ++j ) 
    			printf( "%d", A[ i ][ j ] ), fflush( stdout );
    		printf( "
    " ); fflush( stdout );
    	}
    	return 0;
    }
    
  • 相关阅读:
    Bat脚本处理ftp超强案例解说
    struts2中的输入校验
    struts国际化
    Spring2.5+Hibernate3.3的集成
    SQL Server如果视图存在就删除
    struts2自定义拦截器
    struts2标签
    spring2.5的第一个简单应用的学习
    基于XML配置方式实现对action的所有方法进行校验
    DataGridViewCell 类
  • 原文地址:https://www.cnblogs.com/chy-2003/p/11480350.html
Copyright © 2011-2022 走看看