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[]; int map[][],n,w,h;
int sum[][]; int main()
{
int t;
scanf("%d",&t);
while(t--)
{
cin>>w>>h>>n;
memset(map,,sizeof(map));
memset(sum,,sizeof(sum));
for(int i=; i<=n; i++)
{
cin>>p[i].x>>p[i].y;
map[p[i].x][p[i].y]=;
}
for (int i = ; i <= n; i ++)
{
int xx = p[i].x,yy = p[i].y,x,y,cnt = ;
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 >= ; --y,++cnt);
for (x = xx,y = yy; map[x][y] && x >= ; --x,++cnt);
sum[][i] = cnt;
}
memset(map,,sizeof(map));
for(int i=; i<=n; i++)
{ cin>>p[i].x>>p[i].y;
map[p[i].x][p[i].y]=;
}
for (int i = ; i <= n; i ++)
{
int xx = p[i].x,yy = p[i].y,x,y,cnt = ;
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 >= ; --y,++cnt);
for (x = xx,y = yy; map[x][y] && x >= ; --x,++cnt);
sum[][i] = cnt;
} sort(sum[]+,sum[]++n);
sort(sum[]+,sum[]++n); int falg=;
for(int i=; i<n; i++)
{
if(sum[][i]!=sum[][i])
{
falg=;
break;
}
}
if(!falg)
cout<<"NO"<<endl;
else
cout<<"YES"<<endl;
}
return ;
}
思路:把每个点的值设为连续的x轴点数和连续的y轴点数之和。排序之后,如果相等,则两个图相等。证明的话可想而知

过程:一次A了

代码:
#include
#include int x[],y[];
int map[][];
int left[],right[]; int main(){
int cas;
int i,j,k;
int w,h,n;
int tmp; scanf("%d",&cas);
for(i = ; i < cas; i++){
scanf("%d%d%d",&w,&h,&n); memset(map,,sizeof(map));
for(j = ; j < n; j++){
scanf("%d%d",&x[j],&y[j]);
map[x[j]][y[j]] = ;
} memset(left,,sizeof(left));
for(j = ; j < n; j++){
tmp = x[j];
while(tmp >= &&map[tmp][y[j]] == ){
left[j]++;
tmp--;
} tmp = x[j]+;
while(tmp < w&&map[tmp][y[j]] == ){
left[j]++;
tmp++;
} tmp = y[j]-;
while(tmp >= &&map[x[j]][tmp] == ){
left[j]++;
tmp--;
} tmp = y[j]+;
while(tmp < h&&map[x[j]][tmp] == ){
left[j]++;
tmp++;
}
} memset(map,,sizeof(map));
for(j = ; j < n; j++){
scanf("%d%d",&x[j],&y[j]);
map[x[j]][y[j]] = ;
}
memset(right,,sizeof(right));
for(j = ; j < n; j++){
tmp = x[j];
while(tmp >= &&map[tmp][y[j]] == ){
right[j]++;
tmp--;
} tmp = x[j]+;
while(tmp < w&&map[tmp][y[j]] == ){
right[j]++;
tmp++;
} tmp = y[j]-;
while(tmp >= &&map[x[j]][tmp] == ){
right[j]++;
tmp--;
} tmp = y[j]+;
while(tmp < h&&map[x[j]][tmp] == ){
right[j]++;
tmp++;
}
} for(j = ; j < n; j++){
for(k = ; k < n; k++){
if(left[k-] < left[k]){
tmp = left[k-];
left[k-] = left[k];
left[k] = tmp;
}
}
} for(j = ; j < n; j++){
for(k = ; k < n; k++){
if(right[k-] < right[k]){
tmp = right[k-];
right[k-] = right[k];
right[k] = tmp;
}
}
} for(j = ; j < n; j++){
if(left[j] != right[j]) break;
} if(j == n){
printf("YES\n");
}else{
printf("NO\n");
}
} return ;
}

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

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

    一.(1)  浅拷贝: Mat B; B = image  // 第一种方式 Mat C(image); // 第二种方式 这两种方式称为浅copy,是由于它们有不同的矩阵头,但是它们共享内存空间,即 ...

  2. 【计算机视觉】【图像处理】【VS开发】【Qt开发】opencv之深拷贝及浅拷贝,IplImage装换为Mat

    原文:opencv之深拷贝及浅拷贝,IplImage装换为Mat  一.(1) 浅拷贝: Mat B; B = image // 第一种方式 Mat C(image); // 第二种方式 这两种方式称 ...

  3. 关于opengl中的矩阵平移,矩阵旋转,推导过程理解 OpenGL计算机图形学的一些必要矩阵运算知识

    原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/12166896.html 为什么引入齐次坐标的变换矩阵可以表示平移呢? - Yu Mao的回答 ...

  4. C# DataSet装换为泛型集合

    1.DataSet装换为泛型集合(注意T实体的属性其字段类型与dataset字段类型一一对应) #region DataSet装换为泛型集合 /// <summary> /// 利用反射和 ...

  5. 先装.net后装iis的问题

    如果没有按照正常的先装iis后装.net的顺序,可以使用此命令重新注册一下:(即就是先装的是visual stuido 2010的话,在安装IIS 7) 32位的Windows:----------- ...

  6. oracle中的装换函数

    日期装换成字符的函数:TO_CHAR(date[,fmt[,params]]) 默认格式:DD-MON-RR 参数说明: date:将要装换的日期 fmt:装换的格式 params:日期的语言(可以不 ...

  7. C++实现离散余弦变换(参数为Eigen矩阵)

    C++实现离散余弦变换(参数为Eigen矩阵) 问题描述 昨天写了一个参数为二维指针为参数的离散余弦变换,虽然改进了参数为二维数组时,当数组大小不确定时声明函数时带来的困难,但使用指针作为参数也存在一 ...

  8. 先装IIS后装.Net Framework

    1.动态页面和静态页面的区别 动态页面(动态网站):通过C#代码(或别的语言)与服务器的交互的实现(比如新建一个ashx一般处理程序中的C#代码就可以和服务器实现交互,修改数据库,上传图片等都属于和服 ...

  9. 处理程序“SimpleHandlerFactory-Integrated”在其模块列表中有一个错误模块“ManagedPipelineHandler” 先装 .Net 后装 IIS

    以管理员身份打开 cmd 运行 cd  C:\Windows\Microsoft.NET\Framework\v4.0.30319 运行  aspnet_regiis.exe -i 重新注册 原因是先 ...

随机推荐

  1. Visual Studio 2013 编译CEF步骤

    If you'd like to build the Chromium Embedded Framework (a wrapper for Chromium, for creating browser ...

  2. Java之重载与覆盖

    有的时候,类的同一种功能有多种实现方式,到底采用哪种实现方式,取决于调用者给定的参数.例如我们最常用的System.out.println()能够打印出任何数据类型的数据,它有多种实现方式.运行时,J ...

  3. linux在yum下安装mysql

    1:查看软件是否安装 yum list installed | grep mysql 2:卸载CentOS系统自带mysql数据库 yum -y remove mysql-libs.x86_64,若有 ...

  4. mgo中DBRef-数据添加测试

    2014-1-25 在设计mongo数据库时遇到这样一个问题,日志信息表需要引用人员信息表的数据.如果是结构化数据库,基本上不用想太多的东西.由于刚接触非结构化数据库,按着书上的理解由于日志数量较多, ...

  5. Flume NG简介及配置

    Flume下载地址:http://apache.fayea.com/flume/ 常用的分布式日志收集系统: Apache Flume. Facebook Scribe. Apache Chukwa ...

  6. jquery表格增加删除后改变序号

    有个小bug,懒得修了. 目的:增加一行的时候,td第一列排序. 删除一行的时候,td第一列排序 <!DOCTYPE HTML> <html> <head> < ...

  7. 根据Excel线程句柄得到ID并且关闭进程

    [System.Runtime.InteropServices.DllImport("User32.dll", CharSet = System.Runtime.InteropSe ...

  8. 遇到一个奇葩的问题,could not load the assembly file XXX downloaded from the Web

    在我这编译好好滴,发给客户那边居然不通过,报could not load the assembly file:///xxx.dll, 查阅了一些文档后,发现原来是文件的安全问题,是由于我把文件压缩打包 ...

  9. js常用正则表达式2

    字符 含意 \ 做为转意,即通常在"\"后面的字符不按原来意义解释,如/b/匹配字符"b",当b前面加了反斜杆后/\b/,转意为匹配一个单词的边界. -或- 对 ...

  10. Ajax做分页

    Ajax做分页 用这种ajax做分页的方法比较简单,把代码直接复制就可以,然后根据实际更改一下里面的参数. .设置分页显示显示的样式,显示效果如下. 复制代码 <style type=" ...