• [BFS]翻币问题


    翻币问题

    Description

    有N个硬币(6<=N<=20000)全部正面朝上排成一排,每次将其中5个硬币翻过来放在原位置,直到最后全部硬币翻成反面朝上为止。试编程找出步数最少的翻法,输出最少步数及翻法。


    Input

    从键盘输入一个正整数N(6<=N<=20000),表示硬币的数量。


    Output

    第1行:一个整数,表示最少步数
    第2行至最后一行:先是一个整数,表示步骤序号(从0开始编号),后接一个":",再接当前硬币的状态(用一个整数表示正面朝上的硬币的个数)


    Sample Input

    6


    Sample Output

    6


    解析

    任意翻转5个硬币,正反面的个数变化为:
    5正0反 正-5 反+5
    4正1反 正-3 反+3
    3正2反 正-1 反+1
    2正3反 正+1 反-1
    1正4反 正+3 反-3
    0 正5反 正+5 反-5
    即有6种变化,用state[i]表示节点i正面的个数,完成翻转即正面的个数为0,在执行上面6种翻转时要检查是否符合翻条件,即正面的个数和反面的个数要大于其对应的翻转数,生成新节点时要判断此节点是否出现过,否则就会出现相同的5个硬币翻来翻去的情况。


    代码

    #include<stdio.h>
    #include<iostream>
    using namespace std;
    int n,a[20005],fa[20005],t[20005],ans[20005];
    void bfs(){
    	int head=0,tail=1;
    	a[1]=n;fa[1]=0;ans[1]=0;
    	do{
    		head++; 
    		for(int i=0;i<=5;i++){ //六种可能
    			if(a[head]>=i and n-a[head]>=5-i){ //条件判断
    				tail++;
    				ans[tail]=ans[head]+1;
    				a[tail]=a[head]-i+5-i;
    				fa[tail]=head;
    				if(!t[a[tail]])t[a[tail]]=1; //如果没翻过,就标记
    				 else tail--; 
    				 if(a[tail]==0){
    					printf("%d",ans[tail]);
    					return ;
    				}
    			}
    		}
    	}while(head<=tail);
    }
    int main(){
    	scanf("%d",&n);
    	bfs();
    	return 0;
    }
    
  • 相关阅读:
    JavaEE XML SAX解析
    JavaEE XML DOM解析之DOM4J
    JavaEE XML DOM解析
    JavaEE XML StAX创建
    移动端弹窗后禁止滚动
    vue cli3 项目优化
    【性能优化】quicklink:实现原理与给前端的启发
    关于js异步的一些知识点
    node
    class类
  • 原文地址:https://www.cnblogs.com/luojunhang/p/12300161.html
Copyright © 2020-2023  润新知