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. CGContextRef 绘图

    如何绘制一个矩形 添加一个属性 @property(nonatomic,strong) NSString* RectNumber; 1. 首先重写UIview的drawRect方法 - (void)d ...

  2. JavaScript 为什么要通过原型 prototype 调用函数, 而不是直接调用?

    现象 经常在网上或者阅读源码时看到下面的代码: Array.prototype.slice.call(arr, 3); 而不是 arr.slice(3); 原因 这是为什么呢, 毕竟下面这种方法更短, ...

  3. GTFS

    Documentation The General Transit Feed Specification is documented on a Google Code site. Tables in ...

  4. WebStorage 和 Cookie的区别

    sessionStorage 和 localStorage 是HTML5 Web Storage API 提供的,可以方便的在web请求之间保存数据.有了本地数据,就可以避免数据在浏览器和服务器间不必 ...

  5. web form 控件

    webform的简单控件1.Label:文本显示,编译后是span属性:颜色,样式,边线宽度2.Literal:纯文本显示,编译后是text 3.TextBox:文本框TextMode-密码框.文本域 ...

  6. codeforces 361 D - Friends and Subsequences

    原题: Description Mike and !Mike are old childhood rivals, they are opposite in everything they do, ex ...

  7. 随笔—邀请赛前训— Codeforces Round #330 (Div. 2) B题

    题意: 这道英文题的题意稍稍有点复杂. 找长度为n的数字序列有多少种.这个序列可以分为n/k段,每段k个数字.k个数可以变成一个十进制的数Xi.要求对这每n/k个数,剔除Xi可被ai整除的情况,剔除X ...

  8. linux系统各目录存储的文件类型

    /etc 存储各种配置文件 /etc/init.d/ 目录下包含许多系统各种服务的启动和停止脚本.具体可见:http://blog.csdn.net/gongweijiao/article/detai ...

  9. 关于c#中的console用法大全

    C#之Console   Console.Write  表示向控制台直接写入字符串,不进行换行,可继续接着前面的字符写入.Console.WriteLine  表示向控制台写入字符串后换行.Conso ...

  10. sql中列数据横着显示

    列数据横着显示:CREATE TABLE StudenScore(stuname VARCHAR(25) , kc VARCHAR(25) , fs INT)INSERT INTO StudenSco ...