有N个硬币(6<=N<=20000)全部正面朝上排成一排,每次将其中5个硬币翻过来放在原位置,直到最后全部硬币翻成反面朝上为止。试编程找出步数最少的翻法,输出最少步数及翻法。
从键盘输入一个正整数N(6<=N<=20000),表示硬币的数量。
第1行:一个整数,表示最少步数
第2行至最后一行:先是一个整数,表示步骤序号(从0开始编号),后接一个":",再接当前硬币的状态(用一个整数表示正面朝上的硬币的个数)
输入
6
输出
6
样例解释
0:6 (第0步结果:6个硬币正面朝上)
1:1 (第1步结果:1个硬币正面朝上)
2:4 (第2步结果:4个硬币正面朝上)
3:3 (第3步结果:3个硬币正面朝上)
4:2 (第4步结果:2个硬币正面朝上)
5:5 (第5步结果:5个硬币正面朝上)
6:0 (第6步结果:0个硬币正面朝上)
6 (最少用6步实现全部反面朝上)
由题可得知有6种翻法:
原正个数 | 原负个数 | 翻后正个数 | 翻后负个数 |
---|---|---|---|
5 | 0 | -5 | +5 |
4 | 1 | -3 | +3 |
3 | 2 | -1 | +1 |
2 | 3 | +1 | -1 |
1 | 4 | +3 | -3 |
0 | 5 | +5 | -5 |
判断当前状态是否满足翻的条件,并且翻后状态没有出现过
是就 tail++,放入队尾,将翻后状态=1
如果当前状态正数个数=0,输出步数
别的就套模板啦,我只是个蒟蒻
#include<iostream>
#include<cstdio>
using namespace std;
int a[20100],h,t,n;
int fz[7]={0,5,4,3,2,1,0},ff[7]={0,0,1,2,3,4,5};
struct c{int s,b,f;
}s[20100];
int main()
{scanf("%d",&n);s [1] .s=n; s[1].b=0; s[1].f=0; // 付初值,s 是正数个数,b 是步数,f 是父节点h=0; t=1;a[n]=1; // 状态出现,设为1do{h++;for (int i=1;i<=6;i++)if (s[h].s>=fz[i]&&n-s[h].s>=ff[i]&&a[s[h].s-fz[i]+ff[i]] = = 0)// 判断当前状态是否满足翻的条件,并且翻后状态没有出现过{t++;s[t].s=s[h].s-fz[i]+ff[i];s[t].b=s[h].b+1;s[t].f=h; //放入队尾a[s[t].s]=1; // 保存当前状态出现if (s[t].s = = 0){//int k=s[t].f;//while (k!=0)//{// cout<<s[k].s<<" "<<s[k].b<<endl;// k=s[k].f;//} 用来检测程序,可看每步的正数个数cout<<s[t].b<<endl; //输出最后步数return 0;}}}while (h<t);return 0;
}
本文发布于:2024-01-31 04:35:52,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170664695725530.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |