trytoday 发表于 2010-6-27 15:46

看着车牌忽然想到一个题目,几次变化使之连续

看着车牌忽然想到一个题目,细一想还挺难,不知道是否属于数论分类


比如车牌398276,需要两次变化:把2变成4,3变成5,就成为完全连续的数字了。推广开来,一共有n个不重复的整数,最大不超过max,问需要最多几次变化可以使之全部连续。

例如上面车牌:n=6个不重复整数,最大不超过max=10,需要最多3次变化使之全部连续。

linmatsas 发表于 2010-6-27 16:24

是最少需要几次变化吧…………

yupo_smart 发表于 2010-6-27 19:25

想法很好,可以好好考虑一下。

trytoday 发表于 2010-6-27 21:49

已经能够确定的是:如果 x > (n * (n-1) + 1),表示密度太‘稀’了,这种情况下必然是移动 n - 1次,也就是说保留一个以外都得移动。

另外发现一个简化公式 n - (n*n/x)。用这个公式计算的结果在一些情况有少量误差。
我也没有标准答案来判断误差,只是用随机模拟的方式,对指定的 n x 随机几百次试验确定最有可能的值,以下是代码,效率一般,但n在1000以上几百次模拟也能在几秒内搞定:


C#code:
                private void button1_Click(object sender, EventArgs e)
                {
            //新的描述:编号 1 -- X 的停车位,随机停放 n 辆车,无论当前车辆怎样的位置,最少让多少辆车重新停放
            //          就可以使所有车辆连续停放
            
            int n = int.Parse(textBox1.Text);
            int x = int.Parse(textBox2.Text);

            //500次随机模拟的最接近数字,对比公式计算
            int maxValue = 0;
            for (int i = 0; i < 500; i++)
            {
                int value = randResult(x, n);
                if (maxValue < value) maxValue = value;
                lbMsg.Text = i.ToString();
                lbMsg.Refresh();
            }
            textBox3.Text = maxValue.ToString();

            //这是公式计算的结果,据观察大部分正确,少数误差也不超过 3  :)
            double newValue = (double)n - ((n*n)/(double)x);
            textBox4.Text = newValue.ToString();
                }

        private int randResult(int max, int n)
        {
            if(max <= n) return 0; //error
            if (n < 3) return 0; //error
            if (max < 3) return 0; //error

            int[] lib = new int;
            //随机产生数字来填充
            lib = 1; lib = 1;
            int count = n - 2;
            Random rand = new Random();
            while (count > 0)
            {
                int rnd = rand.Next(1, max);
                if (lib == 0)
                {
                    lib = 1;
                    count--;
                }
            }
            //循环检查最密集区域,也就是需要移动最少的区域
            int min_space = n;
            for (int i = 1; i <= max - n + 1; i++)
            {
                int space = space_count(lib, i, n);
                if (min_space > space) min_space = space;
            }
            return min_space;
        }

        private int space_count(int[] lib, int start, int n)
        {   //检查数组start后面n项数据里面有多少个1
            int count = 0;
            for (int i = start; i < start + n; i++) if (lib == 0) count++;
            return count;
        }

bingcheers 发表于 2010-6-28 12:53

回复 trytoday 的帖子


    牛牛,    牛牛,    牛牛

trytoday 发表于 2010-6-28 22:09

问题已经被另一位高人解决,请参阅:
http://topic.csdn.net/u/20100626/17/5f9a6239-eab1-440b-9bcd-0495bbbb15fc.html

角凳 发表于 2010-9-7 20:20

好像不是很有意义...
页: [1]
查看完整版本: 看着车牌忽然想到一个题目,几次变化使之连续