回 帖 发 新 帖 刷新版面

主题:一个C#的简单题目.

给出一个不大于1 000 000的数a。每次操作,你可以将当前的数中的两个非零位交换位置,并都减去1,得到一个新的数。比如155,我们将百位和个位进行操作,就得到了450.请你的程序输出经过任意次上述的操作,a最大能变成什么数。最好运行的速度不超过1秒。


    题目不是很难,因为是初学者,想请教下高手如何来写这个程序,谢谢!!

回复列表 (共13个回复)

沙发


  有没有知道的朋友啊,不写出代码也可以提示下大概什么思路来做撒~~~

板凳

zjsky830你好,我偶然来到这里,看到你的题目,我不会c#,但可提供一个思路,你不妨试试,
这里假设那个数字是6位数x:

1。把x一位一位地砍到数组里,
   d[1]=x的第1位数字; d[2]=x的第2位数字; ...; d[6]=x的第6位数字;

2。按照6个位置任取2个的组合,生成一个数组,或干脆直接赋值
   a[1]="12"; a[2]="13"; 。。。a[15]="56";

3。for(i=1;i<16;i++){
       e=a[i]的第1位数字;
       f=a[i]的第2位数字;
       对d[e]和d[f]进行题目的操作,判断是否可生成一个新的数字
   }
4。。。。。。。
如果还有什么不清楚,咱们再讨论,祝你编出一个漂亮的程序来。

3 楼

其中有一个条件没看明白,如果交换的位置正好是0,那么0-1等于什么中间有没有借位的问题,如:505十位与个位交换,并且各减1,那么结果是549还是539

4 楼

给一个粗略的算法:

1. a的各位数字,由高位至低位,存进数组arr[].
2. for(int i=0;i<arr.Length;i++){
    if(arr[i]>0)
      for(int j=i+1;j<=arr.Length;j++){
        2.1 找出从j到arr.Length中的最大数字的序号jmax,并且是最靠后的一个;
        2.2 if(arr[i]<arr[jmax]-1)
            arr[i]与arr[jmax]减1互换;
    }
   }

5 楼

[quote]其中有一个条件没看明白,如果交换的位置正好是0,那么0-1等于什么中间有没有借位的问题,如:505十位与个位交换,并且各减1,那么结果是549还是539[/quote]
两个“非零位”交换位置,请仔细看题。

6 楼

/*我写了个从111-1000000中所有数的交换*/



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

namespace StudyOne
{
    class TestClass
    {
        public void TestMethod()
        {
            for (int i =111; i <=1000000; i++)
            {
                //得到一个交换前的数
                int[] intSwap = IntArray(i.ToString());
                
                //构造一个存放任意两位数交换后的新数集合
                ArrayList al = new ArrayList();
            
                //遍历被交换数的每一位数值,产生任意两个数交换后得到的新数放在集合里面
                for (int j = 0; j < intSwap.Length; j++)
                {
                    int temp = intSwap[j];

                    for (int k = 0; k < intSwap.Length - 1; k++)
                    {
                        if (temp!= 0 && intSwap[k+1] != 0)
                        {
                            intSwap[j] = intSwap[k + 1] - 1;
                            intSwap[k + 1] = temp-1;
                             
                            al.Add(ConstructIntNumber(intSwap));

                             intSwap = IntArray(i.ToString());
                        }
                    }
                    intSwap = IntArray(i.ToString());
                }
                
                Console.Write("数值:{0}任意两位交换后得:",i.ToString());
                al.Sort();
                foreach (int   newData in al)
                {
                    Console.Write("  {0}  ", newData);
                }
                
                Console.WriteLine();
            }
        }

        public int[] IntArray(string data)
        {
            char[] beforeSwap = data.ToString().ToCharArray();

            int[] intSwap = new int[beforeSwap.Length];

            for (int i = 0; i < beforeSwap.Length; i++)
            {
                intSwap[i] = Convert.ToInt32(beforeSwap[i].ToString());
            }

            return intSwap;
        }

        public int ConstructIntNumber(int[] intAl)
        {
            string number = string.Empty;
            for (int i = 0; i < intAl.Length; i++)
            {
                number += intAl[i].ToString();
            }

            return Convert.ToInt32(number);
        }
    }
}

7 楼

/*改了一下*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;

namespace StudyOne
{
    class TestClass
    {
        public void TestMethod()
        {
            for (int i =111; i <=1000000; i++)
            {
                //得到一个交换前的数
                int[] intSwap = IntArray(i.ToString());
                
                //构造一个存放任意两位数交换后的新数集合
                ArrayList al = new ArrayList();
            
                //遍历被交换数的每一位数值,产生任意两个数交换后得到的新数放在集合里面
                for (int j = 0; j < intSwap.Length; j++)
                {
                    int temp = intSwap[j];

                    for (int k = j; k < intSwap.Length - 1; k++)
                    {
                        if (temp!= 0 && intSwap[k+1] != 0)
                        {
                            intSwap[j] = intSwap[k + 1] - 1;
                            intSwap[k + 1] = temp-1;
                             
                            al.Add(ConstructIntNumber(intSwap));

                             intSwap = IntArray(i.ToString());
                        }
                    }
                    intSwap = IntArray(i.ToString());
                }
                
                Console.Write("数值:{0}任意两位交换后得:",i.ToString());
                al.Sort();
                foreach (int   newData in al)
                {
                    Console.Write("  {0}  ", newData);
                }
                
                Console.WriteLine();
            }
        }

        private int[] IntArray(string data)
        {
            char[] beforeSwap = data.ToString().ToCharArray();

            int[] intSwap = new int[beforeSwap.Length];

            for (int i = 0; i < beforeSwap.Length; i++)
            {
                intSwap[i] = Convert.ToInt32(beforeSwap[i].ToString());
            }

            return intSwap;
        }

        private int ConstructIntNumber(int[] intAl)
        {
            string number = string.Empty;
            for (int i = 0; i < intAl.Length; i++)
            {
                number += intAl[i].ToString();
            }

            return Convert.ToInt32(number);
        }
    }
}

8 楼

现在题目是这个意思:一个数,交换两个非零数,使之变成“最大”。
我的思路是这样子的:
首先,将个数放到一个数组当中;
然后,从最小位(即个位)开始找起,找到一个最大的数,放到这个临时变量当中temp1;
再者,从最大位(最高位)开始找起,找到一个最小(非零)的数,放到另一个临时变量当中temp2;
最后,将它们(数组)重新组合成一个数,我认为这个数应当就是我们要找的“最大”数了。

如果有什么不当的地方,还请高手指点出来。

9 楼

这个题目,比较复杂的,因为每次交换都有能量损失的,所以,最佳的策略是,尽可能少地减少交换的次数.
  正常情况下,在进行一次交换时,存在多种选择,为了避免不必要的能量损失,只能选择使得交换后的值取最大值、且大于当前值的交换,直到,无法找到这样的交换,则,当前值就是所求的最大值.
  如果,当前值的由高到低的各个非零数位,恰好是降序排列的,还有必要做交换吗?
  如果说:你的目的是,经过无限次的交换<直到不存在这样的交换可能>后的结果,求这样的最大值,那么,问题的关键是考虑,非零数位的值和这些数位的分布情况.总之,是不需要,进行实际的交换运算的.
  这是一个策略性问题.

10 楼

我发现这样一个问题,如果说,本身这个数就是最大的,
即,例如:987,这个数本身就是最大了,是不是说就不用交换了,
直接将个位和百位直接各减一就得了。
大家讨论一下!

我来回复

您尚未登录,请登录后再回复。点此登录或注册