| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 7166 人关注过本帖
标题:【分享】三种“聪明”的全排列函数
取消只看楼主 加入收藏
yu_hua
Rank: 2
等 级:论坛游民
帖 子:222
专家分:95
注 册:2006-8-10
结帖率:71.43%
收藏
已结贴  问题点数:20 回复次数:1 
【分享】三种“聪明”的全排列函数
在24点游戏编程过程中,在“全排列”方面偶有所得,在此与大家分享一下。

第一种“聪明”的全排列函数
int quan_pai_lie(int a[ ],int n)
//这个俺前几年自编的全排列函数很有特色。功能如下
//int型数组 a[ ](n个元素)既是入口参数,也是出口参数。
//进入时要求从大到小排列,如{5,4,3,2,1}。调用1次就变成
//{5,4,3,1,2},再调用就变成{5,4,2,3,1},依此类推。函数
//的返回值通常是1,表示还有未尽的排列;如果返回0,则表示
//给出的排列已经全了。于本例,就是到达{1,2,3,4,5}状态。
//如果初始状态为{1,2,4,5,3},调用后相继出现{1,2,4,3,5}
//{1,2,3,5,4}最终{1,2,3,4,5}。该函数还能正确对待重复
//元素: 设n=4,最初{5,5,5,1},调用后相继出现{5,5,1,5}、
//{5,1,5,5}最终定格在{1,5,5,5}。
//欲改变排序方向,请按末尾带////的行中的提示修改代码
{ //from 5,4,3,2,1 to 1,2,3,4,5
    int i,j,k,temp,t;
    for(k=n-1;k>0;k--)
     if(a[k-1]>a[k])break; ////改为a[k-1]<a[k]
    if(k==0)return 0;
    temp=a[k-1];i=k;
    for(j=k+1;j<n;j++)
     if(temp>a[j]&&a[j]>a[i])i=j; ////两个">"都改为"<"
    a[k-1]=a[i];a[i]=temp;
    for(i=k;i<n-1;i++)
    for(j=k;j<n-1+k-i;j++)
      if(a[j+1]>a[j])      ////改为a[j+1]<a[j]
      {t=a[j];a[j]=a[j+1];a[j+1]=t;}
    return 1;
}   

第二种“聪明”的全排列函数
这个全排列函数permutation()是专门为24点游戏设计,所以它
只能实现4个不同或部分相同元素的全排列。说它“聪明”是指它
能够正确处理雷同元素;而且不要求初始排序。模仿本函数,不难
写出处理5个或更多个元素的全排列代码。
void use2(void(*fun)( ),int a,int b,int c,int d)
{   
     fun(a,b,c,d);if(c-d)
     fun(a,b,d,c);
}   
void use6(void(*f)(),int a,int b,int c,int d)
{   
     use2(f,a,b,c,d);if(b-c)
     use2(f,a,c,d,b);if(b-d)if(c-d)
     use2(f,a,d,b,c);
}   
void permutation(void(*f)(),int a,int b,int c,int d)
{   
     use6(f,a,b,c,d);if(a-b)
     use6(f,b,c,d,a);if(a-c)if(b-c)
     use6(f,c,d,a,b);if(a-d)if(b-d)if(c-d)
     use6(f,d,a,b,c);
}   
//下面的main(void)提示您怎样调用这个全排列函数
#include<stdio.h>
void print(int a,int b,int c,int d)
{   
printf("%d%d%d%d\n",a,b,c,d);
}   
int main(void)
{   
    permutation( print,1,2,3,2 );
    return 0;
}   
屏幕输出如下(vc6.0)
1232
1223
1322
2321
2312
2213
2231
2132
2123
3212
3221
3122
Press any key to continue

第三种“聪明”的全排列函数
全排列函数 use24 为24点游戏设计,也不要求初始排序。
能够实现4个不同、相同或部分相同元素的全排列。特别是  
这个嵌套调用函数的层次感非常好。现在把它介绍给大家。
void use4(void(*fun)( ),int a,int b,int c,int d)
{  //第3层次 组内成员次序
     fun(a,b,  c,d);//甲组a先b后;乙组c先d后
     if(c-d)
     fun(a,b,  d,c);//甲组a先b后;乙组d先c后
     if(a-b)
     fun(b,a,  c,d);//甲组b先a后;乙组c先d后
     if(a-b && c-d)
     fun(b,a,  d,c);//甲组b先a后;乙组d先c后
}   
void use8(void(*f)(),int a,int b,int c,int d)
{  //第2层次 "组"的次序
     use4(f, a,b, c,d);//ab为甲组、cd为乙组
     if(a==c && b==d || a==d && b==c)return;
     use4(f, c,d, a,b);//cd为甲组、ab为乙组
}   
void use24(void(*f)(),int a,int b,int c,int d)
{  //第1层次 两两分组
     use8(f, a,b, c,d);//ab一组、cd另一组
     if(a-c && b-d)
     {  
     use8(f, a,d, b,c);//ad一组、bc另一组
     if(a-b && a-d && b-c && c-d)
     use8(f, a,c, b,d);
     }  
     else if(a-d && b-c)
     {  
     use8(f, a,c, b,d);//ac一组、bd另一组
     if(a-b && a-c && b-d && c-d)
     use8(f, a,d, b,c);//ad一组、bc另一组
     }  
}   
//下面的main(void)提示怎样调用全排列函数use24
#include<stdio.h>
void print(int a,int b,int c,int d)
{   
    printf("%d%d%d%d\n",a,b,c,d);
}   
int main(void)
{   
    use24( print,1,2,2,2 );
    return 0;
}   
屏幕输出如下(vc6.0)
1222
2122
2212
2221
Press any key to continue


搜索更多相关主题的帖子: 函数 排列 分享 
2010-12-05 15:48
yu_hua
Rank: 2
等 级:论坛游民
帖 子:222
专家分:95
注 册:2006-8-10
收藏
得分:0 
其实,代码的长短应该是次要的。
一楼第1个函数长度短、又支持任意个元素的全排列。按理说,似乎已经很好。
但是,为什么要继续研究呢?这是因为,在24点游戏避免重复解的研究过程中
我发现:从全排列意义上,第1个函数给出的“全排列”当然是不带重复的,然
而对于24点那样的游戏就不够友好了。举例:1、2、6、9 四个数字的全排列,
有2、9、1、6;2、9、6、1;9、2、1、6;9、2、6、1;
有1、6、2、9;1、6、9、2;6、1、2、9;6、1、9、2 等等。
如果不另加判断地写“24点”的代码,就会导致“重复度”为8的雷人解
2*9+1*6;2*9+6*1;9*2+1*6;9*2+6*1;
1*6+2*9;1*6+9*2;6*1+2*9;6*1+9*2。
此“故障”的根源在于(a*b)+(c*d)模式的运算,括号内的乘法满足交换律、
括号外的加法也满足交换律!因此,遇见这种双重交换律成立的情况,即使四张
牌的点数不等,也只能停留在“第1层次”即:将它们分为3种组合,具体为
a、b;c、d 如上例中:2、9在一组;1、6在另一组
a、d;b、c 如上例中:2、6在一组;9、1在另一组
a、c;b、d 如上例中:2、1在一组;9、6在另一组
如果括弧外的运算不满足交换律,则应进行到“第2层次”。相当于说
“2、9在甲组;1、6在乙组” 是一种状态;而
“1、6在甲组;2、9在乙组” 是另外一种状态。
如果括弧内的运算也不满足交换律了,则应进行到“第3层次”--这时全排列给
出的所有状态就都得用上啰!“浅尝辄止”不利于研究算法问题。

2010-12-05 16:51
快速回复:【分享】三种“聪明”的全排列函数
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.095562 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved