翻币问题
题目链接:翻币问题
题目描述
有N个硬币(6<=N<=20000)全部正面朝上排成一排,每次将其中5个硬币翻过来放在原位置,直到最后全部硬币翻成反面朝上为止。试编程找出步数最少的翻法,输出最少步数及翻法。
输入格式
从键盘输入一个正整数N(6<=N<=20000),表示硬币的数量。
输出格式
第1行:一个整数,表示最少步数
第2行至最后一行:先是一个整数,表示步骤序号(从0开始编号),后接一个":",再接当前硬币的状态(用一个整数表示正面朝上的硬币的个数)
输入输出样例
输入样例
6
输出样例
6
解题思路
这道题我想了很久很久,然后敲着敲着就AC了…
这道题是BFS,难点在于找出硬币变换的规律,规律如下:
只要找出了规律,那么这道题就比较简单了个鬼啊
程序如下
#include<iostream>
using namespace std;
int n,hd=1,tl=1,a[20010];
const int zx[7]={0,5,4,3,2,1,0};
const int zy[7]={0,0,1,2,3,4,5};
struct abc{
int x,y,ans;
}f[20010];
bool check(int q1,int p1,int q2,int p2)//判断???其实我自己也比较懵
{
if(q1<0||q1>n||q2<0||q2>n)
return 0;
if(p1<0||p1>n||p2<0||p2>n)
return 0;
if(a[q2])
return 0;
return 1;
}
int main()
{
cin>>n;
f[1].x=n;f[1].ans=0;
while(hd<=tl)//BFS
{
for(int i=1;i<=6;i++)
if(check(f[hd].x-zx[i],f[hd].y-zy[i],f[hd].x-zx[i]+zy[i],f[hd].y-zy[i]+zx[i]))
{
tl++;
f[tl].x=f[hd].x-zx[i]+zy[i];
f[tl].y=f[hd].y-zy[i]+zx[i];
f[tl].ans=f[hd].ans+1;
a[f[tl].x]=1;
if(f[tl].x==0)
{
cout<<f[tl].ans<<endl;
return 0;
}
}
hd++;
}
}