2D-Nim

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 4066   Accepted: 1851

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

Source

Tehran 2002, First Iran Nationwide Internet Programming Contest
 
分析:
需要依据题目,提取图像特征,特征一致则为YES,特征不一致则为NO。
解题:
提取了2个特征:
1)每一个点的邻接关系:统计四个方向上邻接点数量分布,即有0、1、2、3、4个点相邻的数量。
2)点的连通量:在纵向和横向两个方向上,统计连线点的分布,即有1、2、...、99、100个点连成一线的数量。
 
PS:这两个条件为必要不充分条件。discus中有用例我没跑过,但是poj AC了,poj的数据弱了。至于充分条件,目前我还没想出如何证明。
 
 #include <stdio.h>
#include <stdlib.h>
#include <string.h> typedef struct
{
int width;
int height;
int num;
int map[][][];
}Picture; typedef struct
{
int x;
int y;
int factor;
}Piont; Picture pic;
Piont points[][];
int factorCnt[][];
int connectCnt[][];
int connectMax[]; void Input()
{
int i, j, x, y = ;
memset(&pic, , sizeof(pic));
scanf("%d %d %d", &pic.width, &pic.height, &pic.num); for(j = ; j < ; j++)
{
for(i = ; i < pic.num; i++)
{
scanf("%d %d", &x, &y);
pic.map[j][y][x] = ;
points[j][i].x = x;
points[j][i].y = y;
}
}
/*
for(j = 0; j < 2; j++)
{
for(y = pic.height-1; y >= 0; y--)
{
for(x = 0; x < pic.width; x++)
{
printf("%d ", pic.map[j][y][x]);
}
printf("\n");
}
printf("------------------------\n");
}
*/
} void CalcFactor()
{
int i, j, x, y, factor;
memset(factorCnt, , sizeof(factorCnt));
for(j = ; j < ; j++)
{
for(i = ; i < pic.num; i++)
{
x = points[j][i].x;
y = points[j][i].y;
factor = (x > ) ? pic.map[j][y][x-] : ;
factor += (x < pic.width-) ? pic.map[j][y][x+] : ;
factor += (y > ) ? pic.map[j][y-][x] : ;
factor += (y < pic.height-) ? pic.map[j][y+][x] : ;
points[j][i].factor = factor;
factorCnt[j][factor]++;
}
}
/*
for(j = 0; j < 2; j++)
{
for(i = 0; i < pic.num; i++)
{
printf("%d ", points[j][i].factor);
}
printf("\n");
}
printf("------------------------\n");
*/
} void CheckResult()
{
int i, j = ;
for(i = ; i < ; i++)
{
if(factorCnt[][i] != factorCnt[][i]) break;
} if(connectMax[] != connectMax[])
{
printf("NO\n");
return;
} for(j = ; j < connectMax[]; j++)
{
if(connectCnt[][j] != connectCnt[][j]) break;
} if(i != || j != connectMax[])
{
printf("NO\n");
}
else
{
printf("YES\n");
}
} void CalcConnect()
{
int j, x, y, connect;
memset(connectMax, , sizeof(connectMax));
memset(connectCnt, , sizeof(connectCnt));
for(j = ; j < ; j++)
{
for(y = ; y < pic.height; y++)
{
for(x = ; x < pic.width; x++)
{
if(pic.map[j][y][x] != ) continue;
connect = ;
while(++x < pic.width && pic.map[j][y][x] == )
{
connect++;
}
connectCnt[j][connect]++;
if(connect > connectMax[j]) connectMax[j] = connect;
}
} for(x = ; x < pic.width; x++)
{
for(y = ; y < pic.height; y++)
{
if(pic.map[j][y][x] != ) continue;
connect = ;
while(++y < pic.height && pic.map[j][y][x] == )
{
connect++;
}
connectCnt[j][connect]++;
if(connect > connectMax[j]) connectMax[j] = connect;
}
}
}
} void Proc()
{
CalcFactor();
CalcConnect();
CheckResult();
} int main()
{
int num = ;
scanf("%d", &num);
while(num--)
{
Input();
Proc();
}
return ;
}
 

北大poj-1021的更多相关文章

  1. 北大POJ题库使用指南

    原文地址:北大POJ题库使用指南 北大ACM题分类主流算法: 1.搜索 //回溯 2.DP(动态规划)//记忆化搜索 3.贪心 4.图论 //最短路径.最小生成树.网络流 5.数论 //组合数学(排列 ...

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

    2D-Nim Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 3081   Accepted: 1398 Descriptio ...

  3. POJ 1021 2D-Nim

    Description The 2D-Nim board game is played on a grid, with pieces on the grid points. On each move, ...

  4. POJ 1021 人品题

    报告见代码.. #include <iostream> #include <cstdio> #include <cstring> #include <algo ...

  5. 【Java】深深跪了,OJ题目Java与C运行效率对比(附带清华北大OJ内存计算的对比)

    看了园友的评论之后,我也好奇清橙OJ是怎么计算内存占用的.重新测试的情况附在原文后边. -------------------------------------- 这是切割线 ----------- ...

  6. POJ 1861 Network (Kruskal算法+输出的最小生成树里最长的边==最后加入生成树的边权 *【模板】)

    Network Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 14021   Accepted: 5484   Specia ...

  7. 各大OJ

    北大POJ 杭电HDU 浙大ZOj 蓝桥杯 PAT

  8. leetcode学习笔记--开篇

    1 LeetCode是什么? LeetCode是一个在线的编程测试平台,国内也有类似的Online Judge平台.程序开发人员可以通过在线刷题,提高对于算法和数据结构的理解能力,夯实自己的编程基础. ...

  9. OJ题目JAVA与C运行效率对比

    [JAVA]深深跪了,OJ题目JAVA与C运行效率对比(附带清华北大OJ内存计算的对比) 看了园友的评论之后,我也好奇清橙OJ是怎么计算内存占用的.重新测试的情况附在原文后边. ----------- ...

  10. C++ 指针常见用法小结

    1. 概论 2.指针基础 3. 指针进阶 4. 一维数组的定义与初始化 5. 指针和数组 6. 指针运算 7. 多维数组和指针 8. 指针形参 9. 数组形参 10. 返回指针和数组 11. 结语   ...

随机推荐

  1. 关于PHP的mkdir函数

    问题:dedecms5.7 php5.6 我想项目根目录下的uploads文件夹下动态创建一个文件夹/uploads/imgs $path = '/uploads/imgs'; mkdir($path ...

  2. helm安装redis+Sentinel集群搭建

    一.redis集群特点 数据 在多个Redis节点之间自动分片 sentinel特点: 它的主要功能有以下几点 不时地监控redis是否按照预期良好地运行; 如果发现某个redis节点运行出现状况,能 ...

  3. 思科模拟器PacketTracer7--利用一台交换机和2台pc互连构成小型局域网

    实验二—2 实验工具:思科模拟器PacketTracer7(可在思科官网下载,免费) 实验设备: 交换机一台,PC两台,直连线或选择自动匹配 实验步骤: 一.配置网络拓扑图 连线可选择连通线或闪电符号 ...

  4. linux top指令信息表示

    top指令: PID ====  进程号 USER ==== 进程所有者 PR ====  进程优先级 NI ====  进程优先级别数值 VIRT ==== 进程占用的虚拟内存 RES ====   ...

  5. [luogu P2633] Count on a tree

    [luogu P2633] Count on a tree 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点 ...

  6. C++标准模板库(STL)之Queue

    1.Queue的常用用法 queue:队列,实现的一个先进先出的容器. 1.1.queue的定义 使用queue,首先要加头文件#include<queue>和using namespac ...

  7. reactjs-swiper react轮播图组件基于swiper

    react轮播图组件基于swiper demo地址:http://reactjs-ui.github.io/reactjs-swiper/simple.html 1. 下载安装 npm install ...

  8. Nginx 作用

    django 请求的生命周期 Nginx 的作用: 浏览器 --- nginx(反向代理器)-- uwsgi --- django项目nginx : 负载均衡, 将任务分发给不同的uwsgi 动静分离 ...

  9. webclient上传数据到ashx服务

    1.上传参数 UploadData()方法可以上传数据参数,需要将所要上传的数据拼成字符. // 创建一个新的 WebClient 实例.    WebClient myWebClient = new ...

  10. Java基本概述

    1.java语言的特点 1.面向对象:基本概念(类,对象) 三大特征:封装.继承.多态 2.健壮性 3.跨平台:通过Java语言的编写的应用程序在不同的系统平台上都能可以进行运行. 2.什么是JDK. ...