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. Entity Framwork(EF) 7——在现在数据库的甚而上开发MVC 新项目

    一.开发背景: 由于老系统已经无法满足实际业务需求,需在现有数据库的甚而上开发新的项目. 二.困难点: 而EF默认情况下是要删除现有数据库表格后重新创建,这是不允许的.当你创建数据库对象时系统会提示“ ...

  2. Eclipse JSP/Servlet 环境搭建

    Eclipse JSP/Servlet 环境搭建 本文假定你已安装了 JDK 环境,如未安装,可参阅 Java 开发环境配置. 我们可以使用 Eclipse 来搭建 JSP 开发环境,首先我们分别下载 ...

  3. Junit测试中的setup和teardown 和 @before 和 @After 方法

    这几天做Junit测试接触到了setup和teardown两个方法,简单的可以这样理解它们,setup主要实现测试前的初始化工作,而teardown则主要实现测试完成后的垃圾回收等工作. 需要注意的是 ...

  4. python之路-Day1

    Python 是一门什么样的语言? python是一门动态解释性的强类型定义语言 动态语言:动态类型语言是指在运行期间才去做数据类型检查的语言,也就是说,在用动态类型的语言编程时,永远也不用给任何变量 ...

  5. call_user_func函数

    <?php function funa($b,$c) { echo $b; echo $c; } call_user_func('funa', "111","222 ...

  6. swift 获取控件位置 大小

    var SearchBtn = uibutton() SearchBtn.frame.origin.x   //获取坐标x SearchBtn.frame.origin.Y  // 获取坐标Y Sea ...

  7. 开发中用到的开源框架汇总(Updating)

    SuperWebSocket SuperSocket NPOI 官网:http://npoi.codeplex.com/ 实例讲解:http://www.cnblogs.com/yutian/p/52 ...

  8. Gradle Android Studio basic

    1. change gradle version in gradle/wrapper/gradle-wrapper.properties  change distributionUrl=http\:/ ...

  9. Ubuntu14.04环境下Samba报错排错过程

    排错的方法和思路非常重要,日志非常非常非常非常重要!!! 搭建好Samba之后,windos访问一直下面这个错误,然后傻逼一样一直百度百度,一弄又是几天,但是经过自己一步一步的排错,弄成功之后,那心情 ...

  10. AngularJS学习--- AngularJS中XHR(AJAX)和依赖注入(DI) step5

    前言:本文接前一篇文章,主要介绍什么是XHR,AJAX,DI,angularjs中如何使用XHR和DI. 1.切换工具目录 git checkout -f step- #切换分支 npm start ...