数码问题合集

数码问题,就不介绍了,百度百度,嘿嘿。

做了一天的数码,郁闷,- -

1、判断数码问题是否有解

原文地址:http://blog.csdn.net/hnust_xiehonghao/article/details/7951173

个人总结:

数码问题判断有解总结:把0看做可移动空格,这里所说的逆序数都是除开0的

一维N:
状态s和状态e的逆序数奇偶性相同,则可相互到达;反之不行

二维N*N:
空格距离:空格位置所在的行到目标空格所在的行步数(不计左右距离)
当N为奇数:状态s和状态e的逆序数奇偶性相同,则可相互到达;反之不行
当N为偶数:状态s和状态e的逆序数奇偶性相同 && 空格距离为偶数 或者 逆序数奇偶性不同 && 空格距离为奇数,则可相互到达;反之不行

三维N*N*N:
空格距离:空格位置到目标状态空格位置的yz方向的距离之和
判断同二维

SWUST OJ 306

15数码问题(0306)

问题描述

将1,2、、14,15这15个数字填入一个4*4的方格中,当然你会发现有个空格方格,我们用数字0来代替那个空格,如下就是一个合理的填入法: 1 2 3 4 5 6 7 8 9 10 0 12 13 14 11 15 现在的问题是:你是否能通过交换相邻的两个数字(相邻指的是上、下、左、右四个方向,而且待交换的两个数字中有一个为数字0),最后变成如下这种排列格式: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0

输入

输入包括两部分: 第一部分:输入一个数C,代表下面共有C组输入 第二部分:输入包括一个4*4的矩阵,矩阵中的数由0,1,2、、15组成。

输出

如果能通过如题方式达到目标排列,输出“YES”,否则输出“NO”。

样例

1

1 2 3 4

5 6 7 8

9 10 0 12

13 14 11 15

YES

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

int main()
{
    int a[20],T,i,j;
    int tot,pos,dis;
    scanf("%d",&T);
    while(T--)
    {
        tot=0;
        for(i=0;i<16;i++)
        {
            scanf("%d",&a[i]);
            if(a[i])
            {
                for(j=0;j<i;j++)
                {
                    if(a[j]>a[i]) tot++;
                }
            }
            else pos=i;
        }
        dis=4-(pos/4+1);
        if(tot%2==dis%2)
            cout<<"YES\n";
        else
            cout<<"NO\n";
    }
    return 0;
}

2、POJ 1077

Eight

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 25376   Accepted: 11106   Special Judge

Description

The 15-puzzle has been around for over 100 years; even if you don‘t know it by that name, you‘ve seen it. It is constructed with 15 sliding tiles, each with a number from 1 to 15 on it, and all packed into a 4 by 4 frame with one tile missing. Let‘s call the missing tile ‘x‘; the object of the puzzle is to arrange the tiles so that they are ordered as:

 1  2  3  4
 5  6  7  8
 9 10 11 12
13 14 15  x 

where the only legal operation is to exchange ‘x‘ with one of the tiles with which it shares an edge. As an example, the following sequence of moves solves a slightly scrambled puzzle:

 1  2  3  4    1  2  3  4    1  2  3  4    1  2  3  4
 5  6  7  8    5  6  7  8    5  6  7  8    5  6  7  8
 9  x 10 12    9 10  x 12    9 10 11 12    9 10 11 12
13 14 11 15   13 14 11 15   13 14  x 15   13 14 15  x
           r->           d->           r-> 

The letters in the previous row indicate which neighbor of the ‘x‘ tile is swapped with the ‘x‘ tile at each step; legal values are ‘r‘,‘l‘,‘u‘ and ‘d‘, for right, left, up, and down, respectively.

Not all puzzles can be solved; in 1870, a man named Sam Loyd was famous for distributing an unsolvable version of the puzzle, and 
frustrating many people. In fact, all you have to do to make a regular puzzle into an unsolvable one is to swap two tiles (not counting the missing ‘x‘ tile, of course).

In this problem, you will write a program for solving the less well-known 8-puzzle, composed of tiles on a three by three 
arrangement.

Input

You will receive a description of a configuration of the 8 puzzle. The description is just a list of the tiles in their initial positions, with the rows listed from top to bottom, and the tiles listed from left to right within a row, where the tiles are represented by numbers 1 to 8, plus ‘x‘. For example, this puzzle

 1  2  3
 x  4  6
 7  5  8 

is described by this list:

 1 2 3 x 4 6 7 5 8 

Output

You will print to standard output either the word ``unsolvable‘‘, if the puzzle has no solution, or a string consisting entirely of the letters ‘r‘, ‘l‘, ‘u‘ and ‘d‘ that describes a series of moves that produce a solution. The string should include no spaces and start at the beginning of the line.

Sample Input

 2  3  4  1  5  x  7  6  8 

Sample Output

ullddrurdllurdruldr

由于这道题是一组数据,所以需要快速解决问题,使用A*算法

好像暴力也可过,不过耗时久,我交了一个,刚好1000MS,好神奇

16MS

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <cmath>
using namespace std;
#define N 400000

int get_h(const char s[])    //估价函数,返回当前状态所有数字与其位置之差的绝对值之和
{
    int sum=0;
    for(int i=0;i<9;i++)
    {
        sum+=abs(s[i]-‘0‘-i-1);
    }
    return sum;
}
struct Eight
{
    int x;
    int g;
    char s[9];
    bool operator < (const Eight &t)const
    {
        return g+get_h(s)>t.g+get_h(t.s);
    }
};
int xpos;
char s[10];
int way[N];
int pre[N];
bool vis[N];
char Dir[5]="udlr";
int dir[4][2]={-1,0,1,0,0,-1,0,1};
int fac[]={1,1,2,6,24,120,720,5040,40320,326880};

int Find(char s[])
{
    int i,j,k,res=0;
    bool has[10]={0};
    for(i=0;i<9;i++)
    {
        for(k=0,j=1;j<s[i]-‘0‘;j++) if(!has[j]) k++;
        res+=k*fac[8-i];
        has[s[i]-‘0‘]=1;
    }
    return res+1;
}
void show()
{
    char ans[N];
    int len=0,pos=1;
    while(pre[pos])
    {
        ans[len++]=way[pos];
        pos=pre[pos];
    }
    for(int i=len-1;i>=0;i--)
    {
        printf("%c",ans[i]);
    }
    printf("\n");
}
void bfs()
{
    Eight now,next;
    priority_queue<Eight> q;
    memset(vis,0,sizeof(vis));
    memset(pre,0,sizeof(pre));
    memset(way,0,sizeof(way));
    now.g=0;
    now.x=xpos;
    strcpy(now.s,s);
    q.push(now);
    vis[Find(now.s)]=1;
    while(!q.empty())
    {
        now=q.top();
        q.pop();
        if(vis[1])
        {
            show();
            return;
        }
        int pos1=Find(now.s);
        int x=now.x/3;
        int y=now.x%3;
        for(int i=0;i<4;i++)
        {
            next=now;
            int tx=x+dir[i][0];
            int ty=y+dir[i][1];
            if(tx>=0 && tx<=2 && ty>=0 && ty<=2)
            {
                next.g+=1;
                next.x=tx*3+ty;
                swap(next.s[now.x],next.s[next.x]);
                int pos2=Find(next.s);
                if(!vis[pos2])
                {
                    vis[pos2]=1;
                    way[pos2]=Dir[i];
                    pre[pos2]=pos1;
                    q.push(next);
                }
            }
        }
    }
    cout<<"unsolvable\n";
}
int main()
{
    while(scanf(" %c",&s[0])!=EOF)
    {
        for(int i=0;i<9;i++)
        {
            if(i) scanf(" %c",&s[i]);
            if(s[i]==‘x‘)
            {
                s[i]=‘9‘;
                xpos=i;
            }
        }
        bfs();
    }
    return 0;
}

3、HDU 1043

Eight

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 12761    Accepted Submission(s): 3475
Special Judge

Problem Description

The 15-puzzle has been around for over 100 years; even if you don‘t know it by that name, you‘ve seen it. It is constructed with 15 sliding tiles, each with a number from 1 to 15 on it, and all packed into a 4 by 4 frame with one tile missing. Let‘s call the missing tile ‘x‘; the object of the puzzle is to arrange the tiles so that they are ordered as:

 1  2  3  4 5  6  7  8 9 10 11 1213 14 15  x

where the only legal operation is to exchange ‘x‘ with one of the tiles with which it shares an edge. As an example, the following sequence of moves solves a slightly scrambled puzzle:

 1  2  3  4     1  2  3  4     1  2  3  4     1  2  3  4 5  6  7  8     5  6  7  8     5  6  7  8     5  6  7  8 9  x 10 12     9 10  x 12     9 10 11 12     9 10 11 1213 14 11 15    13 14 11 15    13 14  x 15    13 14 15  x            r->            d->            r->

The letters in the previous row indicate which neighbor of the ‘x‘ tile is swapped with the ‘x‘ tile at each step; legal values are ‘r‘,‘l‘,‘u‘ and ‘d‘, for right, left, up, and down, respectively.

Not all puzzles can be solved; in 1870, a man named Sam Loyd was famous for distributing an unsolvable version of the puzzle, and 
frustrating many people. In fact, all you have to do to make a regular puzzle into an unsolvable one is to swap two tiles (not counting the missing ‘x‘ tile, of course).

In this problem, you will write a program for solving the less well-known 8-puzzle, composed of tiles on a three by three 
arrangement.

Input

You will receive, several descriptions of configuration of the 8 puzzle. One description is just a list of the tiles in their initial positions, with the rows listed from top to bottom, and the tiles listed from left to right within a row, where the tiles are represented by numbers 1 to 8, plus ‘x‘. For example, this puzzle

1 2 3 
x 4 6 
7 5 8

is described by this list:

1 2 3 x 4 6 7 5 8

Output

You will print to standard output either the word ``unsolvable‘‘, if the puzzle has no solution, or a string consisting entirely of the letters ‘r‘, ‘l‘, ‘u‘ and ‘d‘ that describes a series of moves that produce a solution. The string should include no spaces and start at the beginning of the line. Do not print a blank line between cases.

Sample Input

2 3 4 1 5 x 7 6 8

Sample Output

ullddrurdllurdruldr

题目描述都是一样的,不过这个是多组数据,所以需要预处理

思路同"魔板":http://www.cnblogs.com/hate13/p/4198053.html

109MS

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
using namespace std;
#define N 400000

struct Eight
{
    int x;            //x记录X的位置
    char s[9];
};

int pre[N];
bool vis[N];
char way[N];
char Dir[5]="durl";
int dir[4][2]={-1,0,1,0,0,-1,0,1};
int fac[]={1,1,2,6,24,120,720,5040,40320,326880};

int Find(char s[])
{
    int i,j,k,res=0;
    bool has[10]={0};
    for(i=0;i<9;i++)
    {
        for(k=0,j=1;j<s[i]-‘0‘;j++) if(!has[j]) k++;
        res+=k*fac[8-i];
        has[s[i]-‘0‘]=1;
    }
    return res;
}
void bfs()
{
    Eight now,next;
    queue<Eight> q;

    now.x=8;
    strcpy(now.s,"123456789");
    q.push(now);
    vis[Find(now.s)]=1;
    while(!q.empty())
    {
        now=q.front();
        q.pop();
        int pos1=Find(now.s);
        int x=now.x/3;
        int y=now.x%3;
        for(int i=0;i<4;i++)
        {
            next=now;
            int tx=x+dir[i][0];
            int ty=y+dir[i][1];
            if(tx>=0 && tx<=2 && ty>=0 && ty<=2)
            {
                next.x=tx*3+ty;
                swap(next.s[now.x],next.s[next.x]);
                int pos2=Find(next.s);
                if(!vis[pos2])
                {
                    vis[pos2]=1;
                    pre[pos2]=pos1;
                    way[pos2]=Dir[i];
                    q.push(next);
                }
            }
        }
    }
}
int main()
{
    bfs();
    char s[10];
    while(scanf(" %c",&s[0])!=EOF)
    {
        for(int i=0;i<9;i++)
        {
            if(i) scanf(" %c",&s[i]);
            if(s[i]==‘x‘) s[i]=‘9‘;
        }
        int pos=Find(s);
        if(vis[pos])
        {
            while(pos)
            {
                printf("%c",way[pos]);
                pos=pre[pos];
            }
            printf("\n");
        }
        else
            printf("unsolvable\n");
    }
    return 0;
}

4、HDU 3567

Eight II

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 130000/65536 K (Java/Others)
Total Submission(s): 1243    Accepted Submission(s): 270

Problem Description

Eight-puzzle, which is also called "Nine grids", comes from an old game.

In this game, you are given a 3 by 3 board and 8 tiles. The tiles are numbered from 1 to 8 and each covers a grid. As you see, there is a blank grid which can be represented as an ‘X‘. Tiles in grids having a common edge with the blank grid can be moved into that blank grid. This operation leads to an exchange of ‘X‘ with one tile.

We use the symbol ‘r‘ to represent exchanging ‘X‘ with the tile on its right side, and ‘l‘ for the left side, ‘u‘ for the one above it, ‘d‘ for the one below it.

A state of the board can be represented by a string S using the rule showed below.

The problem is to operate an operation list of ‘r‘, ‘u‘, ‘l‘, ‘d‘ to turn the state of the board from state A to state B. You are required to find the result which meets the following constrains:
1. It is of minimum length among all possible solutions.
2. It is the lexicographically smallest one of all solutions of minimum length.

Input

The first line is T (T <= 200), which means the number of test cases of this problem.

The input of each test case consists of two lines with state A occupying the first line and state B on the second line.
It is guaranteed that there is an available solution from state A to B.

Output

For each test case two lines are expected.

The first line is in the format of "Case x: d", in which x is the case number counted from one, d is the minimum length of operation list you need to turn A to B.
S is the operation list meeting the constraints and it should be showed on the second line.

Sample Input

2
12X453786
12345678X
564178X23
7568X4123

Sample Output

Case 1: 2
dd
Case 2: 8
urrulldr

这个题和上一个一样,显然需要预处理,不过这个需要预处理9张表,由于起始位置都在变,所以建立映射

注意不要使用string,会MLE

还有注意字典序

1248MS

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <map>
using namespace std;
#define N 400000

struct Eight
{
    int x;        //x记录X的位置
    char s[9];
};

bool vis[N];
int pre[10][N];
char way[10][N];
char Dir[]="dlru";
int dir[4][2]={1,0,0,-1,0,1,-1,0};
int fac[]={1,1,2,6,24,120,720,5040,40320,326880};

int Find(char s[])
{
    int i,j,k,res=0;
    bool has[10]={0};
    for(i=0;i<9;i++)
    {
        for(k=0,j=1;j<s[i]-‘0‘;j++) if(!has[j]) k++;
        res+=k*fac[8-i];
        has[s[i]-‘0‘]=1;
    }
    return res;
}
void bfs(int k)
{
    Eight now,next;
    queue<Eight> q;
    memset(vis,0,sizeof(vis));
    now.x=k-1;
    strcpy(now.s,"123456789");
    q.push(now);
    vis[Find(now.s)]=1;
    while(!q.empty())
    {
        now=q.front();
        q.pop();
        int pos1=Find(now.s);
        int x=now.x/3;
        int y=now.x%3;
        for(int i=0;i<4;i++)
        {
            next=now;
            int tx=x+dir[i][0];
            int ty=y+dir[i][1];
            if(tx>=0 && tx<=2 && ty>=0 && ty<=2)
            {
                next.x=tx*3+ty;
                swap(next.s[now.x],next.s[next.x]);
                int pos2=Find(next.s);
                if(!vis[pos2])
                {
                    vis[pos2]=1;
                    pre[k][pos2]=pos1;
                    way[k][pos2]=Dir[i];
                    q.push(next);
                }
            }
        }
    }
}
int main()
{
    bfs(1);
    bfs(2);
    bfs(3);
    bfs(4);
    bfs(5);
    bfs(6);
    bfs(7);
    bfs(8);
    bfs(9);
    int k,i,T,iCase=1;
    char s1[10],s2[10];
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s%s",s1,s2);
        map<char,char> mp;
        for(i=0;i<9;i++)
        {
            if(s1[i]==‘X‘) k=i+1;
            mp[s1[i]]=i+‘1‘;
        }
        for(i=0;i<9;i++)
        {
            s2[i]=mp[s2[i]];
        }
        char ans[N],len=0;
        int pos=Find(s2);
        while(pos)
        {
            ans[len++]=way[k][pos];
            pos=pre[k][pos];
        }
        printf("Case %d: %d\n",iCase++,len);
        for(i=len-1;i>=0;i--) cout<<ans[i];
        printf("\n");
    }
    return 0;
}
时间: 2024-12-16 21:43:17

数码问题合集的相关文章

NOIP提高组 1999 &amp; 2000 题解合集

[序言]话说我在学神奇算法的时候,基础应该也要巩固,于是打算提前把NOIP提高组的刷完. 具体的题目描述和提交我就在VIJOS上完成. [1999.1] 描述 给定一个信封,最多只允许粘贴N张邮票,计算在给定M(N+M<=10)种邮票的情况下(假定所有的邮票数量都足够),如何设计邮票的面值,能得到最大max ,使得1-max之间的每一个邮资值都能得到. 例如,N=3,M=2,如果面值分别为1分.4分,则在l分-6分之间的每一个邮资值都能得到(当然还有8分.9分和12分):如果面值分别为1分.3分

Vim命令合集

来源:Vim命令合集 命令历史 以:和/开头的命令都有历史纪录,可以首先键入:或/然后按上下箭头来选择某个历史命令. 启动vim 在命令行窗口中输入以下命令即可 vim 直接启动vim vim filename 打开vim并创建名为filename的文件 文件命令 打开单个文件 vim file 同时打开多个文件 vim file1 file2 file3 ... 在vim窗口中打开一个新文件 :open file 在新窗口中打开文件 :split file 切换到下一个文件 :bn 切换到上一

[转载]VIM命令合集

Vim命令合集 http://www.cnblogs.com/softwaretesting/archive/2011/07/12/2104435.html 命令历史 以:和/开头的命令都有历史纪录,可以首先键入:或/然后按上下箭头来选择某个历史命令. 启动vim 在命令行窗口中输入以下命令即可 vim 直接启动vim vim filename 打开vim并创建名为filename的文件 文件命令 打开单个文件 vim file 同时打开多个文件 vim file1 file2 file3 ..

前端资源教程合集

综合类 前端知识体系 前端知识结构 Web前端开发大系概览 Web前端开发大系概览-中文版 Web Front-end Stack v2.2 En类资源汇总 免费的编程中文书籍索引 前端书籍 前端免费书籍大全 前端知识体系 免费的编程中文书籍索引 智能社 - 精通JavaScript开发 重新介绍 JavaScript(JS 教程) 麻省理工学院公开课:计算机科学及编程导论 JavaScript中的this陷阱的最全收集--没有之一 JS函数式编程指南 JavaScript Promise迷你书

减肥视频合集

薄荷味视频合集 http://www.boohee.com/posts/view/222199/1?sub_id=3 我最爱练习Insanity http://www.bilibili.com/video/av3596373/

转载:2013计算机视觉代码合集

转载,原文地址http://blog.csdn.net/daoqinglin/article/details/23607079 -------------------------------------------------------------------------- 来源: http://www.yuanyong.org/cv/cv-code-one.html http://www.yuanyong.org/cv/cv-code-two.html http://www.yuanyong

图像滤镜艺术---微软自拍APP滤镜实现合集DEMO

微软最近退出了自家的美颜app,大家有兴趣可以在苹果商店中下载一下看一看,今天,我们要说的便是这款app中的所有滤镜实现问题. 这款app中一共有14款滤镜效果,分别是:自然.增强.1965.X-PRO.布兰登.沧桑.复古.凉爽.迈耶.清晨.柔嫩.深沉.水墨.糖果: 这14款滤镜中,"自然"这一款滤镜是结合人脸识别的,在有人脸识别的情况下,会弹出调节bar,没有人脸时,改效果为默认效果,无法调节:"增强"属于细节的增强与锐化,这里也不算入特效滤镜中去,对于剩下的12

02对话框合集

对话框合集 一.确定对话框AlertDialog() 1.AlertDialog的创建,Builder创建,类似工厂模式2.Builder.show()底层 public AlertDialog show() { AlertDialog dialog = create(); dialog.show(); return dialog; }3.核心代码: public void click1(View view) { Builder builder = new Builder(this);//类似工

最牛叉的街机游戏合集 &amp; 模拟器

亲爱的小伙伴们,是否还记得那年我们玩的疯狂的街机游戏吗,街机中心提供400多个街机游戏,让你爽到底. 例如:拳皇96,拳皇97,恐龙新世纪.名将.快打旋风.惩罚者.魂斗罗.超级玛丽.雪山兄弟.忍者神龟.格斗之王系列.合金弹头系列.侍魂系列.龙虎之拳系列.街头霸王系列.西游释厄传系列和三国战纪系列等经典街机游戏. 性能高的手机可以打开显示设置内的平滑拉伸,缩放模式设置为拉伸至全屏,横屏需要开启系统的自动旋转屏幕.Xperia Play用户可以自定义物理按键,然后把触摸控制可见关闭,屏幕上就不会再显