穷竭搜索:7拼图、Smallest Difference、Backward Digit Sums

一、7拼图

7拼图由8个正方形的卡和这些卡片完全收纳的框构成。每张卡都编号为0, 1, 2, …, 7,以便相互区别。框架中,可以纵向排列2张,横向排列4张卡。
7当拼图开始时,首先把所有的卡放入框架。在框架中只有0的卡可以与上下左右相邻的卡交换位置。例如,当框架的状态为图A时,与0卡的右边相邻的、7的卡交换位置,就变成图B的状态。或者,从图(a)的状态与0卡下面邻接的2卡交换位置的话,成为图c的状态。在图(a)的状态下0卡与上下左右相邻的卡只有7 2卡,此外的位置不允许更换。
游戏的目的是将卡片排列整齐,使图形(d)的状态。请创建一个程序,输入第一个状态,直到卡片排列整齐为止,输出必要的最小麻烦。但是,输入了的卡的状态可以转移到图d的状态。
输入数据以空白分隔符给出1行中的8个数字。这些表示第一状态的卡片排列。例如,图(a)的数字表示为0 7 3 4 2 5 6,图©为2 7 3 4 0 5 1 6。
input
以上格式提供多个谜题。请处理到输入的最后。给定的谜题的数量在1,000以下。
output
请将每个拼图输出到最后一行的最小麻烦。
Sample Input

0 1 2 3 4 5 6 7
1 0 2 3 4 5 6 7
7 6 5 4 3 2 1 0

Output for the Sample Input

0
1
28

题意:
在2*4的方框里随意填充了0到7共八个数字,每一个点位的数字都可以和相邻点位的数字交换位置,通过这样的交换,最终要使得8个数字(0,1,2…7)顺序的从左往右从上到下依次排列,即排列成 :
0 1 2 3
4 5 6 7
7拼图
思路:
深度优先搜索,不断交换某一个元素的位置,可以穷尽所有的情况,不妨不断交换0元素的位置,从01234567这种最特殊的情况开始交换(这种情况交换次数为0),之后0每换一次位置后产生一种新的情况,理所应当的这种情况需要交换的次数为0未交换时情况所需交换次数再加1.以此类推……获得所有情况所需交换次数即可。
代码:

#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <algorithm>
using namespace std;
map<string,int> dp;
int direction[4]={1,-1,4,-4};
void bfs()
{
    queue<string> que;
    que.push("01234567");
    dp["01234567"]=0;
    while(!que.empty())
    {
        string now=que.front();
        que.pop();
        int p=0,i;
        for(i=0;i<8;i++)
        {
            if(now[i]=='0')
            {
                p=i;
                break;
            }
        }
        for(i=0;i<4;i++)
        {
            int n=p+direction[i];
            if(n>=0&&n<=7&&!(p==3&&i==0)&&!(p==4&&i==1))
            {
                string next=now;
                swap(next[p],next[n]);
                if(dp.find(next)==dp.end())
                {
                    dp[next]=dp[now]+1;
                    que.push(next);
                }
            }
        }
    }
}
int main()
{
    bfs();
    string line;
    while(getline(cin,line))
    {
        line.erase(remove(line.begin(),line.end(),' '),line.end());
        cout<<dp[line]<<endl;
    }
    return 0;
}

二、Smallest Difference

Description - 题目描述
给定若干位十进制数,你可以通过选择一个非空子集并以某种顺序构建一个数。剩余元素可以用相同规则构建第二个数。除非构造的数恰好为0,否则不能以0打头。

举例来说,给定数字0,1,2,4,6与7,你可以写出10和2467。当然写法多样:210和764,204和176,等等。最后一对数差的绝对值为28,实际上没有其他对拥有更小的差。

Input - 输入
输入第一行的数表示随后测试用例的数量。
对于每组测试用例,有一行至少两个不超过10的十进制数字。(十进制数字为0,1,…,9)每行输入中均无重复的数字。数字为升序给出,相隔恰好一个空格。

Output - 输出
对于每组测试用例,输出一个以上述规则可获得的最小的差的绝对值在一行。

Sample Input - 输入样例

1
0 1 2 4 6 7

Sample Output - 输出样例

28

思路:
next_permutation(a,a+e)将数组全排列,列出所有的情况。
代码:

#include <iostream>
#include <algorithm>
#include <math.h>
#include <cstdio>
#define INF 0x3f3f3f3f
using namespace std;

int main()
{
    int n;
    cin>>n;
    while(n--)
    {
        int a[1100];
        int e=0;
        while(cin>>a[e++])
        {
            if(getchar()=='\n')
                break;
        }
        if(e==2)
        {
            cout<<abs(a[0]-a[1])<<endl;
            continue;
        }
        int m1,m2,mid,i;
        mid=e/2;
        int res=INF;
        do
        {
            m1=a[0];
            m2=a[mid];
            if(m1==0||m2==0)
                continue;
            for(i=1; i<mid; i++)
            {
                m1=m1*10+a[i];
            }
            for(i=mid+1; i<e; i++)
            {
                m2=m2*10+a[i];
            }
            res=min(res,abs(m1-m2));
        }
        while(next_permutation(a,a+e));
        cout<<res<<endl;
    }

    return 0;
}

三、Backward Digit Sums

FJ 和 他的奶牛们在玩一个心理游戏。他们以某种方式写下1至N的数字(1<=N<=10)。 然后把相邻的数相加的到新的一行数。重复这一操作直至只剩一个数字。比如下面是N=4时的一种例子

3   1   2   4

  4   3   6

    7   9

     16

在FJ回来之前,奶牛们开始了一个更难的游戏:他们尝试根据最后结果找到开始的序列。这已超过了FJ的思考极限。

写一个程序来帮助FJ吧
N和最后的和

Output
满足要求的一行序列。若有多种情况,输出字典序最小的一种

Sample Input

4 16

Sample Output

3 1 2 4

Hint
样例解释

这里还有其他可能的排列,若 3 2 1 4,但 3 1 2 4 是字典序最小的

代码:

#include <iostream>
#include <algorithm>
using namespace std;

int main()
{
    int n,sum,i;
    cin>>n>>sum;
    int a[11],b[11];
    for(i=1; i<=n; i++)
    {
        a[i]=i;
    }
    int d;
    do
    {
        d=n;
        for(i=1; i<=d; i++)
            b[i]=a[i];
        while(d!=1)
        {
            for(i=1; i<d; i++)
                b[i]=b[i]+b[i+1];
            d--;
        }
        if(b[i=1]==sum)
            break;
    }
    while(next_permutation(a+1,a+n+1));
    cout<<a[1];
    for(i=2; i<=n; i++)
        cout<<" "<<a[i];
    cout<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44350170/article/details/102827696