一、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
思路:
深度优先搜索,不断交换某一个元素的位置,可以穷尽所有的情况,不妨不断交换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;
}