poj 1021矩阵平移装换后是否为同一个矩阵

2D-Nim

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 3081   Accepted: 1398

Description

The 2D-Nim board game is played on a grid, with pieces on the grid points. On each move, a player may remove any positive number of contiguous pieces in any row or column. The player who removes the last piece wins. For example, consider the left grid in the following figure.

The player on move may remove (A), (B), (A, B), (A, B, C), or (B,F), etc., but may not remove (A, C), (D, E), (H, I) or (B, G).

For purposes of writing 2D-Nim-playing software, a certain
programmer wants to be able to tell whether or not a certain position
has ever been analyzed previously. Because of the rules of 2D-Nim, it
should be clear that the two boards above are essentially equivalent.
That is, if there is a winning strategy for the left board, the same one
must apply to the right board. The fact that the contiguous groups of
pieces appear in different places and orientations is clearly
irrelevant. All that matters is that the same clusters of pieces (a
cluster being a set of contiguous pieces that can be reached from each
other by a sequence of one-square vertical or horizontal moves) appear
in each. For example, the cluster of pieces (A, B, C, F, G) appears on
both boards, but it has been reflected (swapping left and right),
rotated, and moved. Your task is to determine whether two given board
states are equivalent in this sense or not.

Input

The
first line of the input file contains a single integer t (1 ≤ t ≤ 10),
the number of test cases, followed by the input data for each test case.
The first line of each test case consists of three integers W, H, and n
(1 ≤ W, H ≤ 100). W is the width, and H is the height of the grid in
terms of the number of grid points. n is the number of pieces on each
board. The second line of each test case contains a sequence of n pairs
of integers xi , yi, giving the coordinates of the pieces on the first
board (0 ≤ xi < W and 0 ≤ yi < H). The third line of the test case
describes the coordinates of the pieces on the second board in the same
format.

Output

Your
program should produce a single line for each test case containing a
word YES or NO indicating whether the two boards are equivalent or not.

Sample Input

2
8 5 11
0 0 1 0 2 0 5 0 7 0 1 1 2 1 5 1 3 3 5 2 4 4
0 4 0 3 0 2 1 1 1 4 1 3 3 3 5 2 6 2 7 2 7 4
8 5 11
0 0 1 0 2 0 5 0 7 0 1 1 2 1 5 1 3 3 6 1 4 4
0 4 0 3 0 2 1 1 1 4 1 3 3 3 5 2 6 2 7 2 7 4

Sample Output

YES
NO

问的是点阵图的同构。

应该有比较科学的方法的,但是我看到网上有一个做法是统计十字走的步数的方法。觉得非常神奇。虽然看起来不怎么科学,但是可能是数据比较水,居然能A。大致思路就是统计每个点能向四个方向走的步数的和,再比较这两个图中每个点是否都能找到一个总步数相同的点与之匹配

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>

using namespace std;
struct node
{
    int x;
    int y;
} p[10005];

int map[105][105],n,w,h;
int sum[2][10000];

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        cin>>w>>h>>n;
        memset(map,0,sizeof(map));
         memset(sum,0,sizeof(sum));
        for(int i=1; i<=n; i++)
        {
            cin>>p[i].x>>p[i].y;
            map[p[i].x][p[i].y]=1;
        }
        for (int i = 1; i <= n; i ++)
        {
            int xx = p[i].x,yy = p[i].y,x,y,cnt = 0;
            for (x = xx,y = yy; map[x][y] && y < h; ++y,++cnt);
            for (x = xx,y = yy; map[x][y] && x < w; ++x,++cnt);
            for (x = xx,y = yy; map[x][y] && y >= 0; --y,++cnt);
            for (x = xx,y = yy; map[x][y] && x >= 0; --x,++cnt);
            sum[0][i] = cnt;
        }
        memset(map,0,sizeof(map));
        for(int i=1; i<=n; i++)
        {

            cin>>p[i].x>>p[i].y;
            map[p[i].x][p[i].y]=1;
        }
        for (int i = 1; i <= n; i ++)
        {
            int xx = p[i].x,yy = p[i].y,x,y,cnt = 0;
            for (x = xx,y = yy; map[x][y] && y < h; ++y,++cnt);
            for (x = xx,y = yy; map[x][y] && x < w; ++x,++cnt);
            for (x = xx,y = yy; map[x][y] && y >= 0; --y,++cnt);
            for (x = xx,y = yy; map[x][y] && x >= 0; --x,++cnt);
            sum[1][i] = cnt;
        }

        sort(sum[0]+1,sum[0]+1+n);
        sort(sum[1]+1,sum[1]+1+n);

        int falg=1;
        for(int i=0; i<n; i++)
        {
            if(sum[0][i]!=sum[1][i])
            {
                falg=0;
                break;
            }
        }
        if(!falg)
            cout<<"NO"<<endl;
        else
            cout<<"YES"<<endl;
    }
    return 0;
}
思路:把每个点的值设为连续的x轴点数和连续的y轴点数之和。排序之后,如果相等,则两个图相等。证明的话可想而知

过程:一次A了

代码:
#include
#include

int x[110],y[110];
int map[101][101];
int left[10010],right[10010];

int main(){
    int cas;
    int i,j,k;
    int w,h,n;
    int tmp;

    scanf("%d",&cas);
    for(i = 0; i < cas; i++){
        scanf("%d%d%d",&w,&h,&n);

        memset(map,0,sizeof(map));
        for(j = 0; j < n; j++){
            scanf("%d%d",&x[j],&y[j]);
            map[x[j]][y[j]] = 1;
        }

        memset(left,0,sizeof(left));
        for(j = 0; j < n; j++){
            tmp = x[j];
            while(tmp >= 0&&map[tmp][y[j]] == 1){
                left[j]++;
                tmp--;
            }

            tmp = x[j]+1;
            while(tmp < w&&map[tmp][y[j]] == 1){
                left[j]++;
                tmp++;
            }

            tmp = y[j]-1;
            while(tmp >= 0&&map[x[j]][tmp] == 1){
                left[j]++;
                tmp--;
            }

            tmp = y[j]+1;
            while(tmp < h&&map[x[j]][tmp] == 1){
                left[j]++;
                tmp++;
            }
        }

        memset(map,0,sizeof(map));
        for(j = 0; j < n; j++){
            scanf("%d%d",&x[j],&y[j]);
            map[x[j]][y[j]] = 1;
        }
        memset(right,0,sizeof(right));
        for(j = 0; j < n; j++){
            tmp = x[j];
            while(tmp >= 0&&map[tmp][y[j]] == 1){
                right[j]++;
                tmp--;
            }

            tmp = x[j]+1;
            while(tmp < w&&map[tmp][y[j]] == 1){
                right[j]++;
                tmp++;
            }

            tmp = y[j]-1;
            while(tmp >= 0&&map[x[j]][tmp] == 1){
                right[j]++;
                tmp--;
            }

            tmp = y[j]+1;
            while(tmp < h&&map[x[j]][tmp] == 1){
                right[j]++;
                tmp++;
            }
        }

        for(j = 0; j < n; j++){
            for(k = 1; k < n; k++){
                if(left[k-1] < left[k]){
                    tmp = left[k-1];
                    left[k-1] = left[k];
                    left[k] = tmp;
                }
            }
        }

        for(j = 0; j < n; j++){
            for(k = 1; k < n; k++){
                if(right[k-1] < right[k]){
                    tmp = right[k-1];
                    right[k-1] = right[k];
                    right[k] = tmp;
                }
            }
        }

        for(j = 0; j < n; j++){
            if(left[j] != right[j]) break;
        }

        if(j == n){
            printf("YES\n");
        }else{
            printf("NO\n");
        }
    }

    return 0;
}
时间: 2024-10-22 11:44:13

poj 1021矩阵平移装换后是否为同一个矩阵的相关文章

poj 1021 2D-Nim 模拟

题意: 给两个平面,每个平面上有一些点,相邻的点可构成点集,为两个平面内的点集是够都对应相似.两个点集相似是指经过对称或旋转或平移后相等. 分析: 直接模拟判断. 代码: //poj 1021 //sep9 #include <iostream> #include <vector> #include <algorithm> using namespace std; int w,h,n; int g[128][128]; int vis[128][128]; int di

opencv之深拷贝及浅拷贝,IplImage装换为Mat

一.(1)  浅拷贝: Mat B; B = image  // 第一种方式 Mat C(image); // 第二种方式 这两种方式称为浅copy,是由于它们有不同的矩阵头,但是它们共享内存空间,即指向一个矩阵.当图像矩阵发生变化时,两者相关联,都会变化. (2)深拷贝 Mat B,C; B = image.clone();       // 第一种方式 image.copyTo(C); // 第二种方式 深拷贝是真正的copy了一个新的图像矩阵,此时image,B,C三者相互没有影响. 二.

原生函数和强制类型装换

var a = new String("abc"); console.log(typeof a); //是Object,而不是string 使用new String("abc"); 创建的是字符串 abc 的封装对象,而不是基本类型值"abc". 封装对象 由于基本类型值没有.length和.toString()这样的属性和方法,需要通过封装对象才能访问,此时JavaScript会自动为基本类型值包装一个封装对象,如: var a = "

整数装换为字符串intToArray与字符串转为整数 arrayToInt实现

7.  整数装换为字符串itoa的实现 1 char *intToArray(int number, char *str) 2 { 3 if(str == NULL) 4 { 5 return NULL; 6 } 7 char *ret = str; 8 char *left = str; 9 char temp = '\0'; 10 // 负数的处理 11 if(number < 0) 12 { 13 number = -number; 14 *ret++ = '-'; 15 left++;

DataSet装换为泛型集合 222

#region DataSet装换为泛型集合 /// <summary> /// 利用反射和泛型 /// </summary> /// <param name="dt"></param> /// <returns></returns> public static List<T> ConvertToList<T>(DataTable dt) { // 定义集合 List<T> ts

POJ 1021 人品题

报告见代码.. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 7 const int MAX=105; 8 int dir[4][2]={1,0,-1,0,0,1,0,-1}; 9 int h,w,n; 10 int maze[MAX][MAX]; 11 int maze2[MAX][

修正黑苹果初装Eclipse后Java项目JRE环境丢失

RT,修正黑苹果初装Eclipse后Java项目JRE环境丢失,原因未知.目测,MBP/A上可能也会有. 菜单操作 Eclipse->Preferences...->Java->Installed JREs 如果有问题列表中应该没有任何条目,此处点击Add->Standard VM 选择JRE home后的Directory,找到JRE的位置,我这里是"/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/

oracle中的装换函数

日期装换成字符的函数:TO_CHAR(date[,fmt[,params]]) 默认格式:DD-MON-RR 参数说明: date:将要装换的日期 fmt:装换的格式 params:日期的语言(可以不写)例子: SQL> select to_char(sysdate,'YYYY-MM-DD HH24:MI:SS') from dual; TO_CHAR(SYSDATE,'YY ------------------- 2016-04-21 07:55:54 字符型转换成日期的函数: TO_DATE

Conversion of feet/inches to meters-英尺、英里装换为米

Conversion of feet/inches to meters-英尺.英里装换为米,允许重复计算: //Conversion of feet/inches to meters-英尺.英里装换为米,允许重复计算 #include<iostream> #include<cmath> using namespace std; void get_input(double& feet,double& inch); double convert(double&