java之图论运用-宽搜

问题描述:
9个硬币排成3*3的二维距阵,正面为T,反面为H,在一次翻转中,若翻转其中一个硬币,则与之上下左右相邻的硬币也要翻转,对于一个给定的硬币排列,试求出使每个硬币均正面朝上的最小翻转次数。示例:

init         1           2
HHH         HHH         TTT
TTT -->     THT -->     TTT
HHH         TTT         TTT

题目分析:我们可以用0表示H,1表示T,则每个硬币的排列可表示为一个二进制数,如:HHHHHHTTT,表示为000000111,即十进的制的7。而最终状态即为111111111,即511。则题目可以转化为,给定一个数,按题目中的翻转方法,求最终得到511的最小翻转次数。
我们需要建一个包含512个结点的图,运用宽搜的方法获得以结点”511”为根的树,然后求从任意一个结点到结点”511”的最短路径。代码如下:
其中,类AbstractGraph,和类UnweightedGraph请见java之图论

import AbstractGraph;
import UnweightedGraph;
import java.util.*;
public class NineTailModel {
    public static void main(String[] args) {
        System.out.print("Enter an initial nine coin H's and T's");
        Scanner input = new Scanner(System.in);
        String s = input.nextLine();
        char[] initialNode = s.toCharArray();
        NineTailModel model = new NineTailModel();
        List<Integer> path = model.getShortestPath(NineTailModel.getIndex(initialNode));
        System.out.println("the steps to flip the coins are");
        for(int i =0;i<path.size();i++){
            NineTailModel.printNode(NineTailModel.getNode(path.get(i).intValue()));
        }
    }
    public final static int NUMBER_OF_NODES = 512;
    protected AbstractGraph<Integer>.Tree tree;   //以结点"511"为根的树
    public NineTailModel(){
        List<AbstractGraph.Edge> edges = getEdges(); 
        UnweightedGraph<Integer> graph = new UnweightedGraph<Integer>(edges, NUMBER_OF_NODES);
        tree = graph.bfs(511);
    }
    /*
     * 获得图的所有的边
     */
    private List<AbstractGraph.Edge> getEdges(){
        List<AbstractGraph.Edge> edges = new ArrayList<AbstractGraph.Edge>();
        for(int u=0;u<NUMBER_OF_NODES;u++){
            for(int k=0;k<9;k++){
                char[] node = getNode(u);
                if(node[k]=='H'){
                    int v = getFlippedNode(node,k);
                    edges.add(new AbstractGraph.Edge(v, u));
                }
            }
        }
        return edges;
    }
    /*
     * 对参数node的第position个位置进行翻转,
     * 返回翻转之后的结点
     */
    public static int getFlippedNode(char[] node,int position){
        int row = position/3;
        int column = position%3;
        flipACell(node,row,column);
        flipACell(node,row-1,column);
        flipACell(node,row+1,column);
        flipACell(node,row,column-1);
        flipACell(node,row,column+1);
        return getIndex(node);
    }
    public static void flipACell(char[] node,int row,int column){
        if(row>=0 && row<=2 && column>=0 &&column<=2){
            if(node[row*3+column]=='H')
                node[row*3+column]='T';
            else
                node[row*3+column]='H';
        }
    }
    /*
     * 硬币正反面排列转化为十进制数
     */
    public static int getIndex(char[] node){
        int result = 0;
        for(int i=0;i<9;i++)
            if(node[i]=='T')
                result = 2*result+1;
            else
                result = 2*result;
        return result;
    }
    /*
     * 十进制数转化为硬币正反面排列
     */
    public static char[] getNode(int index){
        char[] result = new char[9];
        for(int i=0;i<9;i++){
            int digit = index%2;
            if(digit==0){
                result[8-i]='H';
            }else{
                result[8-i]='T';
            }
            index = index/2;
        }
        return result;
    }
    public List<Integer> getShortestPath(int nodeIndex){
        return tree.getPath(nodeIndex);
    }
    public static void printNode(char[] node){
        for(int i=0;i<9;i++){
            if(i%3 != 2){
                System.out.print(node[i]);
            }else
                System.out.println(node[i]);
        }
        System.out.println();
    }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值