好题,6666

转自:http://www.cnblogs.com/kuangbin/archive/2012/08/23/2652410.html

题意:给出一个board,上面有24个位置,其中23个位置上放置了标有数字1~23的方块,一个为空位(用数字0表示),现在可以把空位与它旁边的方块交换,给出board的起始状态,问是否可以达到指定的状态。

思路:看起来很像著名的“八数码”问题,首先,针对八个特殊位置(死角),如果这里有空位就把它和相邻的位置交换,这样之后如果两个状态的对应死角上的数字不同,那么显然是不能达到指定状态的,因为无法把死角处的数字换出去。

搞定了死角后就只剩下4×4的board了,这就变成了八数码问题的拓展——15数码。首先想想八数码是如何判断有解的:首先把所有数字(不包括空
位的0)写成一行,就得到了一个1~8的排列,考虑空位的交换情况:1.左右交换,2.上下交换。对于左右交换而言,是不会改变写出的排列的逆序数的;而
对上下交换,相当于在排列中向前或向后跳了两个位置,那么要么两个数都比它大或小,这样逆序数加2或减2,要么两个数一个比它大一个比它小,这样逆序数不
变,综上,对于八数码问题,操作不会改变逆序数的奇偶性,所以只有初始状态和指定状态的逆序数奇偶性相同就有解。

弄清楚了八数码,扩展起来就容易了,现在我们将其扩展到N维(即N*N的board,N*N-1数码问题)。

首先无论N的奇偶,左右交换不改变逆序数,N为奇数时:上下交换逆序数增加N-1或减少N-1或不变,因为N为奇数,所以逆序数奇偶性不变;而N为偶数时:上下交换一次奇偶性改变一次。

结论:N为奇数时,初始状态与指定状态逆序数奇偶性相同即有解;N为偶数时,先计算出从初始状态到指定状态,空位要移动的行数m,如果初始状态的逆序数加上m与指定状态的逆序数奇偶性相同,则有解。

好了,现在这道题就简单了,计算逆序数和空格要移动的行数即可。

 #include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
int a[];
int b[];
int c[];
int d[];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
for(int i=;i<;i++)
scanf("%d",&a[i]);
for(int i=;i<;i++)
scanf("%d",&b[i]);
//将八个死角的空转过来
if(a[]==)swap(a[],a[]);
if(a[]==)swap(a[],a[]);
if(a[]==)swap(a[],a[]);
if(a[]==)swap(a[],a[]);
if(a[]==)swap(a[],a[]);
if(a[]==)swap(a[],a[]);
if(a[]==)swap(a[],a[]);
if(a[]==)swap(a[],a[]); if(b[]==)swap(b[],b[]);
if(b[]==)swap(b[],b[]);
if(b[]==)swap(b[],b[]);
if(b[]==)swap(b[],b[]);
if(b[]==)swap(b[],b[]);
if(b[]==)swap(b[],b[]);
if(b[]==)swap(b[],b[]);
if(b[]==)swap(b[],b[]);
bool flag=true;
if(a[]!=b[])flag=false;
if(a[]!=b[])flag=false;
if(a[]!=b[])flag=false;
if(a[]!=b[])flag=false;
if(a[]!=b[])flag=false;
if(a[]!=b[])flag=false;
if(a[]!=b[])flag=false;
if(a[]!=b[])flag=false;
if(flag==false)
{
printf("Y\n");
continue;
}
//转化为n数码问题
for(int i=;i<;i++)
{
c[i]=a[i+];
d[i]=b[i+];
}
for(int i=;i<;i++)
{
c[i]=a[i+];
d[i]=b[i+];
}
for(int i=;i<;i++)
{
c[i]=a[i+];
d[i]=b[i+];
}
//求逆序数
int cnt1=;
int cnt2=;
int m1=,m2=;
for(int i=;i<;i++)
{
if(c[i]==)
{
m1=i;
continue;
}
for(int j=;j<i;j++)
{
if(c[i]<c[j])cnt1++;
}
}
for(int i=;i<;i++)
{
if(d[i]==)
{
m2=i;
continue;
}
for(int j=;j<i;j++)
{
if(d[i]<d[j])cnt2++;
}
}
m1/=;//行数
m2/=;//行数
int m=abs(m1-m2); if(((cnt1+m)%)!=(cnt2%))flag=false;
if(flag)printf("N\n");
else printf("Y\n");
}
return ;
}

hdu 4021 n数码的更多相关文章

  1. Eight POJ - 1077 HDU - 1043 八数码

    Eight POJ - 1077 HDU - 1043 八数码问题.用hash(康托展开)判重 bfs(TLE) #include<cstdio> #include<iostream ...

  2. HDU 1043 八数码(八境界)

    看了这篇博客的讲解,挺不错的.http://www.cnblogs.com/goodness/archive/2010/05/04/1727141.html 判断无解的情况(写完七种境界才发现有直接判 ...

  3. HDU 1043 八数码问题的多种解法

    一.思路很简单,搜索.对于每一种状态,利用康托展开编码成一个整数.于是,状态就可以记忆了. 二.在搜索之前,可以先做个优化,对于逆序数为奇数的序列,一定无解. 三.搜索方法有很多. 1.最普通的:深搜 ...

  4. HDU 1043 八数码(A*搜索)

    在学习八数码A*搜索问题的时候须要知道下面几个点: Hash:利用康托展开进行hash 康托展开主要就是依据一个序列求这个序列是第几大的序列. A*搜索:这里的启示函数就用两点之间的曼哈顿距离进行计算 ...

  5. HDU 1043 八数码 Eight A*算法

    Eight Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  6. Eight hdu 1043 八数码问题 双搜

    Eight Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  7. hdu 1043 八数码问题

    Eight Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  8. hdu 4021 24 Puzzle ( 逆序数判断是否可解 )

    24 Puzzle Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others) Total ...

  9. 逆向bfs搜索打表+康拓判重

    HDU 1043八数码问题 八数码,就是1~8加上一个空格的九宫格,这道题以及这个游戏的目标就是把九宫格还原到从左到右从上到下是1~8然后最后是空格. 没了解康托展开之前,这道题怎么想都觉得很棘手,直 ...

随机推荐

  1. squid 学习笔记

    Squid学习笔记 1.安装前的配置 编译安装之前需要校正的参数主要包括File Descriptor和Mbuf Clusters. 1.File Descriptor 查看文件描述符的限制数目: u ...

  2. MD5 Message Digest Algorithm MD5(中文名为消息摘要算法第五版)

    MD5 编辑 Message Digest Algorithm MD5(中文名为消息摘要算法第五版)为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护.该算法的文件号为RFC 1321( ...

  3. git基础知识总结

    1,clone git clone https://github.com/KoMiles/helloword helloword 2,pull git pull 3,commit git commit ...

  4. ASP.NET MVC学习笔记-----使用自定义的View Engine

    我们都知道在ASP.NET MVC中自带了Razor View Engine,Razor十分的强大,可以满足我们绝大部分的需要.但是ASP.NET MVC的高度可扩展性,使我们可以使用自定义的View ...

  5. ReactJS入门学习二

    ReactJS入门学习二 阅读目录 React的背景和基本原理 理解React.render() 什么是JSX? 为什么要使用JSX? JSX的语法 如何在JSX中如何使用事件 如何在JSX中如何使用 ...

  6. macOSX 访问 win7共享文件

    macOSX 访问 win7共享文件 macOSX 访问 win7共享文件 2014年1月8日星期三 开年的第一篇写下自己使用macos中遇到的问题.为后来初学者提供一些浅薄经验. 第一步:WINDO ...

  7. 在VMware上面安装Solaris 10

    导读 Oracle Solaris 11 是世界上最先进的企业操作系统,提供安全.速度.简单的企业云环境和DevOps.在这篇文章中我们将使用Solaris 10版本,但您可以按照同样的步骤,来安装刚 ...

  8. 【ERROR】使用jquery的ajax出现error:readyState=4,status=500

    使用jquery的ajax出现error:readyState=4,status=500,ajax代码如下: $.ajax({ url : "../toBeFinMisManage/show ...

  9. fsck检查和修复文件系统

    重视:fsck不能乱用.先要把文件系统umount掉,然后检查.最好启动到单用户模式下fsck. 常见的5种损坏类型 1 未被引用的inode 2 难以置信的超大链接数 3 没有记录在磁盘块映射表中的 ...

  10. macosx zsh下安装rvm和ruby

    1)curl -L get.rvm.io | bash -s stable 2)把下面一行加到~/.zshrc中: [[ -s "$HOME/.rvm/scripts/rvm" ] ...