Algorithm 版 (精华区)

发信人: Lerry (想不开·撞树), 信区: Algorithm
标  题: [合集]全排列
发信站: 哈工大紫丁香 (2002年08月13日10:03:18 星期二), 站内信件


────────────────────────────────────────
 feelcycle (无是)                     于 发信站: 北大未名站 (2002年08月12日12:07:12 星期一), 转信
用回溯法,首先,N个数也不需要一定是1~N,
(ps.全排列有什么用呢?11位就耗4s,每加1位就长1个数量级还多)
只要可以排序出来,是单调的就可以,
首先做一次排序,递增递减都可以,
然后就转换成了对1~N的排序,排序出来将对应的值换为Data[i]就可以了,
也就是说,最后都转换为了1~N自然数的排序。
设置结果存放的数组,R[N],
设标志位进到第几位,设为i,不说那么多了,看代码
void Series(int N){
        int i,j;
        int *iR=new int[N];
        short *bUsed=new short[N];//第i个数是否已经使用
        for(j=0;j<N;j++) bUsed[j]=0;
        i=0;//初始化
        iR[0]=0;
        bUsed[0]=1;
        while(1){
                i++;//进位,下一位重新搜索开始
                j=0;
                while(j<N){
                        if(!bUsed[j]){//找到了
                                bUsed[j]=1;
                                iR[i]=j;
                                break;
                        }
                        j++;
                }
                if(j==N)
                        i=i;//没有找到退回
                else if(i==N-1){//如果找到了,输出
                        for(j=0;j<N-1;j++){
                                cout<<iR[j]<<",";
                        }
                        cout<<iR[N-1]<<endl;
                        bUsed[iR[i]]=0;//准备回退
                }
                else continue;
                //注意是否要回溯了
back:   if(i==0) break;//退无可退,表示已经搜索完全,退出
                i--;//没有找到当前项,回退一项
                bUsed[iR[i]]=0;//取消回退项的使用标志
                j=iR[i]+1;//从下一个位置找起
                while(j<N){
                        if(!bUsed[j]){//找到了
                                bUsed[j]=1;
                                iR[i]=j;
                                break;
                        }
                        j++;
                }
                if(j==N) goto back;//如果没有找到,那么继续回退,
                //这里使用goto没有破坏结构化,因为完全可以用加while嵌套完成
        }
        delete iR;
        delete bUsed;
}


────────────────────────────────────────
 DailyByte (DailyByte)                于 发信站: 北大未名站 (2002年08月13日00:37:48 星期二), 转信
构造生成,速度快,效率高
#include <iostream.h>
#include <stdlib.h>
const int max = 1001;
int n,list[max];
int main()
{
   int i,maxi;
   for(;;) {
      cin >> n;
      if (n<=0 || n>max) break;
      for (i=1;i<=n;i++)
         list[i] = -i;
      for (;;) {
         cout << "# ";
         for (i=1;i<n;i++)
            cout << abs(list[i]) << ' ';
         cout << abs(list[n]) << endl;
         maxi = 0; list[0] = 0;
         for (i=1;i<=n;i++)
            if (abs(list[i]) > abs(list[maxi])) {
               if ((list[i]<0 && i>1 && abs(list[i-1])<abs(list[i]))||
                   (list[i]>0 && i<n && abs(list[i+1])<abs(list[i]))  )
                  maxi = i;
            }
         if (maxi==0) break;
         if (list[maxi]>0) {
            list[0] = list[maxi];
            list[maxi] = list[maxi+1];
            list[maxi+1] = list[0];
            maxi++;
         } else {
            list[0] = list[maxi];
            list[maxi] = list[maxi-1];
            list[maxi-1] = list[0];
            maxi--;
         }
         for (i=1;i<=n;i++)
            if (abs(list[i])>abs(list[maxi]))
               list[i] = -list[i];
      }
   }
   return 1;
}


────────────────────────────────────────
 feelcycle (无是)                     于 发信站: 北大未名站 (2002年08月13日09:51:35 星期二), 转信
怎么说呢,全排列,想多快是不可能的,
所以千万慎用速度快,给你个12就够你难受一阵子,
其次就是回溯法在认为编程水平等条件一致的情形下是
最快的算法,下面是我的算法和你的算法的对比,
我拿掉了你的最外层循环,直接将n作为参数:
在10的情形下,debug版:
我的算法是690ms,你的算法是2564ms.
本来没想比速度的,看见你的速度快,效率高,
而且max居然定义为1001,实在忍不住了,
就算是100,你的机器能算出来吗???
ps.上面比较时其实都拿掉了屏幕输出的代码。

────────────────────────────────────────
--
※ 修改:·Lerry 於 08月13日10:04:06 修改本文·[FROM: 天外飞仙]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:2.496毫秒