注册 登录
编程论坛 C++教室

用1,2,3,4,5,6,7,8,9这9个数,不能重复使用,组成四位数

棱风柳木 发布于 2009-11-16 16:16, 6508 次点击
用1,2,3,4,5,6,7,8,9这9个数,不能重复使用,组成四位数(如:1234,4582)
程序实现把所有的可能四位数放到数组arr[3024];//所有四位数的可能是3024

谁有好的算法,不是能实现就行那种.
25 回复
#2
东陆小生2009-11-16 20:57
四重循环试试
for(i=1;i<=9;i++)
   for(j=1;j<=9;j++)
     for(h=1;h<=9;h++)
       for(l=1;l<=9;l++)
       {
         a=i*1000+j*100+h*10+l;
         cout<<a;
        }
#3
shl3052009-11-16 21:32
四重循环是可以的,不过要判断四个数两两不同,不能直接输出
#4
东陆小生2009-11-16 23:55
回复 2楼 东陆小生
对 没看清题意 那就加个判断条件喽
if(i==j || i==h || i==l || j==h || j==l || h==l)
  continue;
然后再
a=~~~~;
cout<<a;
#5
flyingcloude2009-11-17 00:14
回复 4楼 东陆小生
for(int i=1;i<=9;i++)
{
   for(int j=1;j<=9;j++)
   {
    if(i==j)
        continue;
     for(int h=1;h<=9;h++)
     {
    if(i==h||j==h)
        continue;
       for(int l=1;l<=9;l++)
       {
    if(l==i||l==j||l==h)
        continue;
       }
     }
   }
}

会少一些循环
#6
棱风柳木2009-11-17 14:33
四重循环也太简单了吧
我在百度知道上提问 有一个叫 aund1986回答;
#include<stdio.h>
void MakeNums(int index,int limit,int pick[],int *nums,int *Index_arr,int *arr,int times);
int NotContains(int *nums,int n,int index);
int MakeNum(int nums[],int limit);
int main()
{
 int i;
 int Index_arr = 0,arr[3024],nums[4];
 int pick[10]={1,2,3,4,5,6,7,8,9,'\0'};
 int t = sizeof(arr);
 MakeNums(0,4,pick,nums,&Index_arr,arr,3024);
 for(i = 0;i<Index_arr;i++)
  printf("%d\n",arr[i]);
 return 0;
}
/*
index:位数下标,用于标识现在循环到了某次整数的第几位
limit:标志是几位数
pick:筛选序列,pick以'\0'结尾
nums:存放整数的每一位的数组
Index_arr:作为最终存放所有符合条件的生成数的数组的下标
arr:存放所有的数
times:生成多少个数,没有本参数程序正常运行,但是某种情况下会降低性能
*/
void MakeNums(int index,int limit,int pick[],int *nums,int *Index_arr,int *arr,int times)
{
 int i;
 if(index < limit)
 {
  for(i = 0;pick[i]!='\0';i++)
   if(NotContains(nums,pick[i],index) == 1)
   {
    *(nums+index) = pick[i];
    MakeNums(index+1,limit,pick,nums,Index_arr,arr,times);   
   }
 }
 else if(index == limit)
 {
  *(arr+*Index_arr) = MakeNum(nums,limit);
  (*Index_arr)++;
  if(*Index_arr == times)
  {
   return;
  }
 }
 
}
/*
判断某个数是否在数组中
nums:数组
n:某个数
index:需要判断到数组的第几个元素
*/
int NotContains(int *nums,int n,int index)
{
 int i;
 for(i = 0;i<index;i++)
 {
  if(*(nums+i) == n)
   return 0;
 }
 return 1;
}
/*
利用数组累加生成整数
nums:数组
limit:生成几位数
*/
int MakeNum(int nums[],int limit)
{
 int i,sum = 0;
 for(i = 0;i<limit;i++)
  sum = sum*10+nums[i];
 return sum;
}
给大家分享下
还有没有比这更好的算法
#7
flyingcloude2009-11-17 18:30
回复 6楼 棱风柳木
程序代码:
int NotContains(int *nums,int n,int index)
{
int i;
for(i = 0;i<index;i++)
{
  if(*(nums+i) == n)
   return 0;
}
return 1;
}
单看这段代码,就觉得这个算法的性能不如四重循环
#8
kspliusa2009-11-17 23:02
我的想法:
代码如下:
#include <cstdlib>
#include <iostream>

using namespace std;

int main()
{
    int temp;
    int n[4] = {0};
    int k;
    int count = 0;
    for (int i=1001; i<10000; i++){
        bool flag  = true;
        temp = i;
        k=0;
        while (temp != 0){
             n[k++] = temp % 10;
             temp /= 10;
        }
        for (int j=0; j<k; j++){
            for (int g=j+1; g<k; g++){
                if (n[j] == n[g]||n[j] == 0){
                   flag = false;
                   break;
                }
            }
            if (!flag)
                break;
        }
        if (flag){
            cout<<i<<endl;
            count++;
        }
    }
    cout<<"count = "<<count<<endl;
    return 0;
}
#9
kspliusa2009-11-17 23:36
改了一下  思想不变
#include <cstdlib>
#include <iostream>

using namespace std;

int main()
{
    int temp;
    int n[4] = {0};
    int k;
    int count = 0;

    for ( int i = 1001; i < 10000; i++ ){
        bool flag  = true;
        temp = i;
        k = 0;
        while ( temp != 0 ){
            n[k] = temp % 10;
            for (int h=0; h<k;h++){
                if (n[h] == n[k]||n[h]==0){
                    flag = false;
                        break;
                }
            }
            if(!flag)
                break;
            temp /= 10;
            k++;
        }
        if (flag){
            cout << i << endl;
            count++;
        }
    }
    cout << "count = " << count << endl;

    return 0;
}
#10
中学者2009-11-18 11:58
直接DFS不就好了.
#include <cstdio>
bool isU[9] = {false};
int count_ = 0;
void find(int dep)
{
    if(dep==4) { //find the fourth
        for(int i=0;i<9;++i){
            if(isU[i]==true){
                printf("%d",i+1);
            }
        }
        printf("   ");
        ++ count_ ;
        return ;
     }
     for(int i=0;i<9;++i){
         if(isU[i]==false){
            isU[i] = true;
            find(dep+1);
            isU[i] = false;
          }
     }
}
int main()
{
     find(0);
     printf("\nThe Sum is %d\n",count_);
     return 0;
}
#11
莫云今次2009-11-18 13:14
顶楼上的     学过算法的人跟没学过算法的人,处理问题果然不一样
#12
kspliusa2009-11-18 13:29
回复 10楼 中学者
出来的结果感觉好像有问题吧~
#13
中学者2009-11-18 13:35
回复 12楼 kspliusa
哪组?
#14
棱风柳木2009-11-18 15:41
先把我在百度知道上的提问放在这吧,让你们也可以看看其他人的回答
http://zhidao.baidu.com/question/125747074.html?quesup1
#15
棱风柳木2009-11-18 16:38
回复 10楼 中学者
呵呵 是个不错的算法
#16
kspliusa2009-11-18 16:42
回复 12楼 kspliusa
你的结果中有重复的数 例如 1234
你的程序我改了改  

#include <cstdio>
#include <iostream>

using namespace std;
bool isU[9] = {false};

int count_ = 0;

int tmp[4] = {0};

void find( int dep )
{

    if ( dep == 4 ) { //find the fourth
        int h1=0;
        for ( int i = 0;i < 9;++i ){
            if ( isU[i] == true ){
                //printf( "%d", i + 1 );
                tmp[h1++] = i+1;
            }
        }

        //printf( "\n" );

    int temp = 1000*tmp[0]+100*tmp[1]+10*tmp[2]+tmp[3];
    if (1234 == temp)
        cout<<"have"<<endl;

        ++ count_ ;

        return ;
    }

    for ( int i = 0;i < 9;++i ){
        if ( isU[i] == false ){
            isU[i] = true;
            find( dep + 1 );
            isU[i] = false;
        }
    }
}

int main()
{
    find( 0 );
    printf( "\nThe Sum is %d\n", count_ );
    return 0;
}
#17
中学者2009-11-18 17:03
已经判过重,怎么会有重复的???
#18
中学者2009-11-18 17:28
晕,发现错了...实在杯具...
#include <cstdio>
bool isU[9] = {false};
int p[4] = {0};
int count_ = 0;
void find(int dep,int now)
{
    if(dep==4) { //find the fourth
        for(int i=0;i<4;++i){
            printf("%d",p[i]);
        }
        printf("   ");
        ++ count_ ;
        return ;
     }
     for(int i=0;i<9;++i){
         if(isU[i]==false){
            isU[i] = true;
            p[now] = i+1;
            find(dep+1,now+1);
            isU[i] = false;
          }
     }
}
int main()
{
     find(0,0);
     printf("\nThe Sum is %d\n",count_);
     return 0;
}
#19
棱风柳木2009-11-18 18:40
回复 10楼 中学者
偶 认真看了下 怎么和我在6楼发的原理差不了多少的?
#20
棱风柳木2009-11-18 19:37
偶这里有两个算法 一个是字典顺序,一个是旋转法;
字典的如下:
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 20
#define SWAP(x,y){int temp;temp=x;x=y;y=temp;}
void main()
{
    int perm[MAXSIZE];
    int last;
    int n;
    int left,right,i,j;
    char line[100];
    gets(line);
    n=atoi(line);
    for(i=0;i<n;i++)
        perm[i]=i+1;
    for(last=0;last>=0;){
        printf("\n");
        for(i=0;i<n;i++)
            printf("%d ",perm[i]);
        for(last=n-2;last>=0&&perm[last]>perm[last+1];last--);
        for(j=n-1;perm[last]>perm[j];j--);
        SWAP(perm[last],perm[j]);
        for(left=last+1,right=n-1;left<right;left++,right--)
            SWAP(perm[left],perm[right]);
    }
}

旋转如下:
#include<stdio.h>
#include<stdlib.h>

#define MAXSIZE 20
#define ROTATE(p){                       \
                  int i,temp;            \
                  temp=perm[p];          \
                  for(i=p-1;i>=0;i--)    \
                      perm[i+1]=perm[i]; \
                  perm[0]=temp;          \
                 }
void main()
{
    int perm[MAXSIZE];
    int position;
    int n;
    int i;
    char line[100];
    printf("\nPermutation by Rotation Method");
    printf("\n==============================");
    printf("\n\nNumber of Elements --> ");
    gets(line);
    n=atoi(line);
    for(i=0;i<n;i++)
        perm[i]=i+1;
    position=n-1;
    while(position!=0){
        printf("\n");
        for(i=0;i<n;i++)
            printf("%d ",perm[i]);
        position=n-1;
        ROTATE(position);
        while(perm[position]==position+1&&position!=0){
            position--;
            ROTATE(position);
        }
    }
}
字典的没写输出提示;将就下吧

我想恳请高手帮我改下使它用在这程序;

这两个程序我是在 c语言名题精选百则(技巧篇)冼镜光编著,这里找到的
#21
棱风柳木2009-11-22 19:25
这里结贴时间到了,要结贴了,如果谁还想说两句请到这吧!
是同一个问题
http://tieba.baidu.com/f?ct=335675392&tn=baiduPostBrowser&sc=6985510842&z=669413411&pn=0&rn=30&lm=0&word=c#6985510842
#22
棱风柳木2009-11-22 19:27
原来不用结贴咯
#23
flyingcloude2009-11-22 23:22
以下是引用棱风柳木在2009-11-22 19:27:25的发言:

原来不用结贴咯
你给问题点数的,就需要结贴。
给问题点数的话,可能更多的人会参与进来。
#24
一旋无风2009-11-23 23:02
貌似没怎么看懂,能注释一下不?我是新来的啦,比较迟钝,大哥有时间注释一下吧
#25
一旋无风2009-11-23 23:04
回复 10楼 中学者
能注释下不?不胜感激!
#26
我心无疆2009-11-24 23:42
www. 其中有一篇文章,专门讲这种组合问题。使用递归处理的,文章名字叫《permulation in C++》,去看一下这个。应该就是以下的代码,可能有些参考,看看吧!另外,这个网站非常好,推荐大家都去看看!
#include <string>
#include <iostream>

using namespace std;

void string_permutation( std::string& orig, std::string& perm )
{
    if( orig.empty() )
    {
        std::cout<<perm<<std::endl;
        return;
    }

    for(int i=0;i<orig.size();++i)
    {
        std::string orig2 = orig;

        orig2.erase(i,1);

        std::string perm2 = perm;

        perm2 += orig.at(i);

        string_permutation(orig2,perm2);
    }
}

int main()
{
    std::string orig="ABCDE";
    std::string perm;

    string_permutation(orig,perm);

    cout<<"Complete!"<<endl;

    system("pause");

    return 0;
}
1