广搜,智能拼图(ZOJ1079)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=79

解题报告:

思路简单,写法太难。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

///x,y的增量
int dx[4] = {1,0,-1,0};
int dy[4] = {0,1,0,-1};
int queue[501];
int used[500];

///使用数组piece表示拼图的每一片的信息
struct {
    int id;        ///这一片,他的相邻的片的编号
    int side;    ///这一片,他的相邻片的邻边的编号
}piece[500][4];

///使用数组pos保存拼图的位置信息,输出结果
struct position{
    int x, y;    ///坐标
    int id;        ///卡片的编号
    int side;    ///下底的编号
}pos[500];

int compare(const void *a,const void *b)
{
    int c;
    if((c=(((struct position*)a)->x-((struct position*)b)->x))!=0)
        return(c);
    return((((struct position*)a)->y-((struct position*)b)->y));
}

int main()
{
    int n, k;    ///卡片的数量和k个卡片的信息量
    int i;
    int cases = 1;

    while(scanf("%d", &n) && n)
    {
        scanf("%d", &k);
        memset(piece, 255, sizeof(piece));
        memset(used, 0, sizeof(used));
        int a, b, c, d;
        for(i=0; i<k; i++)
        {
            scanf("%d%d%d%d", &a, &b, &c, &d);
            piece[a][b].id = c;
            piece[a][b].side = d;
            piece[c][d].id = a;
            piece[c][d].side = b;
        }

        ///编号初始化
        for(i=0; i<n; i++)
            pos[i].id = i;

        pos[0].x = 0;
        pos[0].y = 0;
        pos[0].side = 0;
        used[0] = 1;
        queue[0] = 0;

        int first = 0;    ///队列的头部位置
        int count = 0;    ///队列的尾部位置

        ///队列还没有搜索完毕
        while (first<=count)
        {
            ///搜索当前节点
            a = queue[first];    ///编号
            int x0 = pos[a].x;
            int y0 = pos[a].y;
            d = pos[a].side;
            int number;            ///相邻卡片的编号

            ///对相邻卡片的4边搜索
            for(i=0; i<4; i++)
            {
                ///输入数据有卡片的信息
                if((number=piece[a][i].id)>=0)
                    ///该卡片还没有搜过
                    if(used[number]==0)
                    {
                        b = piece[a][i].side;
                        used[number] = 1;

                        ///计算相邻卡片的位置和底边的信息

                        ///x&3相当于(x+4)%4
                        pos[number].x = x0+dx[(i-d)&3];
                        pos[number].y = y0+dy[(i-d)&3];
                        pos[number].side = ((b-i+d+2)&3);

                        ///该卡片进入队列
                        queue[++count] = number;
                    }
            }
            first++;    ///搜索下一个节点
        }
        qsort(pos, n, sizeof(position), compare);
        a = pos[0].x;
        b = pos[0].y;
        printf("Instance %d:\n",cases++);
        for(i=0; i<n; i++)
            printf("%5d%5d%6d%2d\n", pos[i].x-a, pos[i].y-b, pos[i].id, pos[i].side);
    }
    return 0;
}
时间: 2024-08-06 16:03:07

广搜,智能拼图(ZOJ1079)的相关文章

双向广搜

双向广搜 (2011-08-31 16:45:24)   Eight    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 讲到双向广搜,那就不能不讲经典的八数码问题,有人说不做此题人生不完整 . 所谓双向广搜,就是初始结点向目标结点和目标结点向初始结点同时扩展,直至在两个扩展方向上出现同一个结点,搜索结束.它适用的问题是,扩展结点较多,而目标结点又处在深沉,如果采用单纯的广搜解题,搜索量巨大,搜索速度慢是可想而知的,同时往往也会出现内存空

NYOJ 284 坦克大战 &amp;&amp; POJ 2312 Battle City (广搜+优先队列)

链接:click here~~ 题意: 描述 Many of us had played the game "Battle city" in our childhood, and some people (like me) even often play it on computer now. What we are discussing is a simple edition of this game. Given a map that consists of empty space

Catch That Cow(广搜)

个人心得:其实有关搜素或者地图啥的都可以用广搜,但要注意标志物不然会变得很复杂,想这题,忘记了标志,结果内存超时: 将每个动作扔入队列,但要注意如何更简便,更节省时间,空间 Farmer John has been informed of the location of a fugitive cow and wants to catch her immediately. He starts at a point N (0 ≤ N ≤ 100,000) on a number line and t

codevs 1225:八数码难题【双向广搜】

这里是传送门 这道题用普通BFS是可以做的,但是很明显没得过,效率太低了.效率更高的算法A*和双向广搜都可取,这写一下双向广搜的. 注意题目中的判重很重要,可以转化成九位数用hash来解决这个问题. #include <set> #include <string> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define

迷宫广搜

上学期学了C,这学期学C++.感觉最难的还是算法,上周作业的一道广搜题是我第一次接触广搜,由于第一学期刚学编程就接触的太多的算法难题,不禁对代码产生畏惧,不过还好没有放弃,虽然算法很难,但我慢慢找到了一点学数学时的乐趣.先介绍一下这道未来的我看过来会觉得很简单一道题吧 You are provided a maze(迷宫), and you need to program to find the least steps to walk from the start to the end.And

宽搜和广搜、

广搜与深搜的小区别 一般来说,广搜常用于找单一的最短路线,或者是规模小的路径搜索,它的特点是"搜到就是最优解", 而深搜用于找多个解或者是"步数已知(好比3步就必需达到前提)"的标题,它的空间效率高,然则找到的不必定是最优解,必需记实并完成全数搜索,故一般情况下,深搜需要很是高效的剪枝(优化). 像搜索最短路径这些的很显著若是用广搜,因为广搜的特征就是一层一层往下搜的,保证当前搜到的都是最优解,当然,最短路径只是一方面的操作,像什么起码状态转换也是可以操作的.深搜就

hdu1241详解 Java广搜搞定

import java.util.Scanner; public class Main{ public static void main(String[] args) { Scanner sc = new Scanner(System.in); while (sc.hasNext()) { int m = sc.nextInt();//输入地图的行数 int n = sc.nextInt();//输入地图的列数 if (m == 0) {//若m=0则退出程序 break; } // 初始化图

poj 1166 The Clocks 记录路径的广搜

题意: 给9个时钟的初始状态,和一些对某几个钟的操作,求最少经过几步能到目标状态(全指向12点). 分析: 明显的广搜,但实现起来的细节要注意:1.因为要记录路径,所以要在整个程序执行过程中扩展出的节点在输出路径前不能销毁, 故采用静态内存分配的方法(开node[600000],用get_node()创建节点.2.queue<node>比queue<int>要多花1别的时间. //poj 1166 //sep9 #include <iostream> #include

nyoj 523 双向广搜

题目链接: http://acm.nyist.net/JudgeOnline/problem.php?pid=523 #include<iostream> #include<cstdio> #include<queue> using namespace std; /* 用普通搜索TLE,已知起点和终点,可以考虑双向广搜或A*算法加速搜索 双向广搜,一个方向从出发点向终点搜索,一个方向从终点向出发点搜索,搜索到相同的结点时,即找到最短路径. */ const int N