001 Phone Numbers

解题思路:DF

1002. Phone Numbers

源代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

    class Program
    {
        //存放字母表
        private static Dictionary<char, int> m_WordsDic; 
        //int是每个word在callnumber中匹配的index位置,每个index对应的point可能是多个
        private static Dictionary<int,List<Point>> m_Wordspath;
        //将每个word转为digital
        private static List<Words> m_Digitals;

        private static Mark[] m_MinPath;

        static void Main(string[] args)
        {
            while (true)
            {
                //初始化
                Init();
                string callNum;
                int n;
                //第一行是call number
                callNum = Console.ReadLine();
                if (callNum == "-1")
                    break;
                //第二行是下面有多少word
                n = int.Parse(Console.ReadLine());
                //进行word存储
                //word转化为数字
                InitDigitalDic(n);
                //生成wordPathDic
                InitPathDic(callNum);

                m_MinPath=new Mark[callNum.Length];
                for (int i = 0; i < callNum.Length; i++)
                {
                    m_MinPath[i]=new Mark();
                }
                InitPathMin(callNum.Length);
                if (m_MinPath[callNum.Length-1].Num == 0)
                {
                    //没有找到路径
                    Console.WriteLine("No solution.");

                }
                else
                {
                    foreach (Point point in m_MinPath[callNum.Length-1].MarkPoints)
                    {
                        var markResult = new List<Point> {point};
                        if (OutPutResult(point, markResult, m_MinPath[callNum.Length - 1].Num))
                            break;
                    }
                }
            }
            //Console.ReadLine();
        }

        private static bool OutPutResult(Point point,List<Point> mark,int count)
        {
            if (count == 1 && point.StartIndex != 0)
            {
                //搜寻失败
                return false;
            }
            //是否到达原点
            if(point.StartIndex==0)
            {
                //换行,开始下一个最短解
                OutPutMark(mark);
                return true;
            }
            //如果没到达原点,那么继续往上回溯
            foreach (Point p in m_MinPath[point.StartIndex-1].MarkPoints)
            {
                mark.Add(p);
                if (OutPutResult(p, mark, (count - 1)))
                    return true;
                mark.Remove(p);
            }
            return false;
        }

        private static void OutPutMark(List<Point> mark)
        {
            StringBuilder sb=new StringBuilder();
            for (var i = mark.Count-1; i >=0; i--)
            {
                sb.Append(string.Format("{0} ", mark[i].Words.Letters));   
            }
            Console.WriteLine(sb.ToString(0, sb.Length - 1));
        }

        private static void InitPathMin(int n)
        {
            List<Point> StartList = null;
            if (m_Wordspath.TryGetValue(0, out StartList))
            {
                //初始化第一点
                foreach (Point point in StartList)
                {
                    NextPoint(point, n);
                }
            }
        }
        private static void AddMark(ref Mark mark,int num,Point point)
        {
            mark.Num = num;
            mark.MarkPoints.Add(point);
        }
        private static void NextPoint(Point prePoint,int n)
        {
            List<Point> list = null;
            int index = prePoint.EndIndex + 1;
            //开始对该点最小值进行对比生成
            if(!MinPoint(prePoint))
                return;
            if (prePoint.EndIndex == n)
            {
                //如果是终点,直接返回
                return;
            }
            //如果dic这点无值,意味着死路
            if(!m_Wordspath.TryGetValue(index,out list))
            {
                return;
            }
            //获得以该index作起始点的list
            foreach (Point point in list)
            {
                //开始层的搜寻
                NextPoint(point, n);
            }
        }
        private static bool MinPoint(Point point)
        {
            var mark = m_MinPath[point.EndIndex];
            int temp = 1;
            //如果是第一点
            if (point.StartIndex - 1 >= 0)
                temp = m_MinPath[point.StartIndex - 1].Num + 1;
            if (mark.Num == 0)
            {
                //如果未初始化,直接赋值
                AddMark(ref mark, temp, point);
                return true;
            }
            if(temp<mark.Num)
            {
                mark.MarkPoints.Clear();
                AddMark(ref mark, temp, point);
                return true;
            }
            if (temp == mark.Num)
            {
                if (!NotContains(mark, point))
                {
                    AddMark(ref mark, temp, point);
                    return false;
                }
            }
            return false;
        }

        private static bool NotContains(Mark mark, Point point)
        {
            return mark.MarkPoints.Any(r => r.StartIndex == point.StartIndex && r.EndIndex == point.EndIndex&&r.Words.Letters==point.Words.Letters);
        }

        private static void InitPathDic(string callNum)
        {
            foreach (Words mDigital in m_Digitals)
            {
                FindNextIndex(0,callNum, mDigital);
            }
        }
        private static void FindNextIndex(int startIndex,string lest,Words words)
        {
            //如果未找到,那么就返回
            int index = lest.IndexOf(words.Digital);
            if (index == -1)
                return;
            int endIndex = index + words.Digital.Length - 1;
            AddPoint(index + startIndex, endIndex + startIndex, words);
            FindNextIndex(index + 1 + startIndex, lest.Substring(index + 1), words);
            //index += startIndex;
            ////如果找到了,添加point,用剩下的stirng继续找匹配
            //int lastIndex = index + words.Digital.Length;
            //AddPoint(index, lastIndex, words);
            //FindNextIndex(startIndex + 1, lest.Substring(1), words);
        }
        private static void AddPoint(int startIndex,int lastIndex,Words words)
        {
            List<Point> temp = null;
            if(m_Wordspath.TryGetValue(startIndex,out temp))
            {
                //如果已经存在该项,那么不做添加
                if (!temp.Any(r => r.StartIndex == startIndex && r.EndIndex == lastIndex && r.Words == words))
                    temp.Add(new Point(startIndex, lastIndex, words));
            }
            else
            {
                m_Wordspath[startIndex] = new List<Point>() { new Point(startIndex, lastIndex, words) };  
            }
        }
        private static void InitDigitalDic(int n)
        {
            for (int i = 0; i < n; i++)
            {
                string lineValue = Console.ReadLine();
                var sb = new StringBuilder();
                foreach (char c in lineValue)
                {
                    sb.Append(m_WordsDic[c]);
                }
                m_Digitals.Add(new Words(sb.ToString(), lineValue));
            }
        }

        private static void Init()
        {
            m_Digitals = new List<Words>();
            m_WordsDic = new Dictionary<char, int>()
                             {
                                 {'i', 1},
                                 {'j', 1},
                                 {'a', 2},
                                 {'b', 2},
                                 {'c', 2},
                                 {'d', 3},
                                 {'e', 3},
                                 {'f', 3},
                                 {'g', 4},
                                 {'h', 4},
                                 {'k', 5},
                                 {'l', 5},
                                 {'m', 6},
                                 {'n', 6},
                                 {'p', 7},
                                 {'r', 7},
                                 {'s', 7},
                                 {'t', 8},
                                 {'u', 8},
                                 {'v', 8},
                                 {'w', 9},
                                 {'x', 9},
                                 {'y', 9},
                                 {'o', 0},
                                 {'q', 0},
                                 {'z', 0},
                             };
            m_Wordspath = new Dictionary<int, List<Point>>();
        }
    }

    class  Point
    {
        public int StartIndex;
        public int EndIndex;
        public Words Words;

        public Point(int startIndex,int endIndex,Words letters)
        {
            StartIndex = startIndex;
            EndIndex = endIndex;
            Words = letters;
        }
    }

    class Words
    {
        public string Digital;
        public string Letters;
        public Words(string digital,string letter)
        {
            Digital = digital;
            Letters = letter;
        }
    }

    class Mark
    {
        public int Num;
        public List<Point> MarkPoints;

        public Mark()
        {
            MarkPoints = new List<Point>();
        }
    }

  

原文地址:https://www.cnblogs.com/suriyel/p/2795470.html