zoukankan      html  css  js  c++  java
  • [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;
    }
    
  • 相关阅读:
    Django框架 之 logging配置
    Django框架 之 中间件
    Django框架 之 form组件
    Django框架 之 Ajax
    Django框架 之 Pagination分页实现
    3张图带你看懂扩展KMP(EXKMP)
    [TJOI2018]游园会(状压dp+LCS)
    [BZOJ 2959] 长跑(LCT+并查集)
    [NAIPC2016]Jewel Thief(决策单调性+分治)
    [BZOJ 1563] [NOI 2009] 诗人小G(决策单调性)
  • 原文地址:https://www.cnblogs.com/luojunhang/p/12300161.html
Copyright © 2011-2022 走看看