c程序在交换条件下以升序排列最少数量的交换来排列1到3的3x3数组

时间:2014-04-09 14:44:21

标签: c algorithm sorting

PS-我没有很多编程经验,我是这一切的新手。所以请帮我解决这个问题,这是我在大学里的一个项目。

游戏条件:如果它们的总和是素数,你可以交换两个相邻的牌。如果两个图块具有共同边缘,则认为它们是相邻的。

这是一个问题 http://www.codechef.com/problems/H1

虽然那里有解决方案,但我无法理解它们。

我一直在研究这个问题,但我无法解决这个问题。

我做的第一个程序随机交换任意两个图块(遵循条件)。这样它就可以计算掉期。对于容易出问题,它很可能会找到最少的计数。但对于复杂的,它几乎没有。它根本没有效率。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int a[]={1,3,2,4,5,6,7,8,9};
int b[]={1,2,3,4,5,6,7,8,9};
int c[9];
int count=0;

void swap(){
    int p,q,tmp;
for(p=0;p<9;p++){
    for(q=p+1;q<9;q++){
            if(prime(a[p],a[q])&&position(p,q)){
    if(a[p]>a[q]){
        tmp=a[p];
        a[p]=a[q];
        a[q]=tmp;
        count++;
    }
    }
    }
    }
    printf("\n\nswapstart\n\n");
    for(p=0;p<9;p++){
        printf("%d ", a[p]);
    }
    printf("\n\nswapover\n\n");
}

int prime(int a, int b){
int c=a+b;
if(c==3||c==5||c==7||c==11||c==13||c==17){
    return 1;
}
return 0;
}

int position(int a, int b){
if((a-b==1||b-a==1||a-b==3||b-a==3) && (!((a==2&&b==3)||(a==3&&b==2)||(a==5&&b==6)||(a==6&&b==5))))
    return 1;
else
    return 0;
}

int main()
{
    int i,j,temp,cnd=0,m,times=1000,finalcount=10000000;

    srand(time(NULL));

   for(m=0;m<9;m++){
            c[m]=a[m];
        }
while(times--){

   for(m=0;m<9;m++){
            if(a[m]==b[m]){
               cnd=1;
               }
                else{
                    cnd=0;
                    break;
                }
        }
   while(cnd==0){

    i=rand()%9;
    j=rand()%9;

    if(prime(a[i],a[j])&&position(i,j)){
        temp=a[i];
        a[i]=a[j];
        a[j]=temp;
        count++;

        for(m=0;m<9;m++){
            if(a[m]==b[m]){
               cnd=1;
               }
                else{
                    cnd=0;
                    break;
                }
        }
    }
   }

for(m=0;m<9;m++){
    printf("%d ", a[m]);
    a[m]=c[m];
}
if(count<finalcount){
    finalcount=count;
}
printf("remaining = %d count= %d, finalcount= %d\n", times, count, finalcount);
count=0;
cnd=0;
}
    return 0;
}

其次我做了另一个节目。它首先瞄准最小数量,即1,然后它试图将它带到第0个位置。如果它没有这样做,那么它会转到2.依此类推。它也能够以某种方式解决基本问题(不是以最小的方式而已),而不是更复杂的问题。

#include <stdio.h>
#include <stdlib.h>

int a[]={2,6,3,1,4,5,7,9,8},b[]={1,2,3,4,5,6,7,8,9},c[9];

int i,j,m,trgt=1,temp,cnt=0;

int prime(int a, int b){
int c=a+b;
if(c==3||c==5||c==7||c==11||c==13||c==17){
    return 1;
}
return 0;
}

int position(int a, int b){
if((a-b==1||b-a==1||a-b==3||b-a==3) && (!((a==2&&b==3)||(a==3&&b==2)||(a==5&&b==6)||(a==6&&b==5))))
    return 1;
else
    return 0;
}

int condition(){
for(m=0;m<9;m++){
    if(a[m]==b[m]);
    else
        return 1;
}
return 0;
}

int cond(){
    if(a[trgt-1]==trgt)
        return 0;
    else
        return 1;
}

int block(){
    int p;
for(p=0;p<9;p++){
    if(a[p]==c[p]);
    else{
        return 1;
    }
}
return 0;
}

void target(int t){
    for(m=0;m<9;m++){
        c[m]=a[m];
        printf("%d ", a[m]);
    }
    printf("\n");
    while(cond()){

    j=rand()%9;
if(prime(a[t],a[j])&&position(t,j)){
    temp=a[t];
    a[t]=a[j];
    a[j]=temp;
    t=j;
    cnt++;
}
if(block()){
    break;
}
}
}

int main()
{
            while(condition()){
        for(i=0;i<9;i++){
        if(a[i]==trgt){
            target(i);
        trgt++;
        }
    }
    trgt=1;
    }
    printf("Hello world!\n");
    for(i=0;i<9;i++){
        printf("%d ", a[i]);
    }
    return 0;
}

请告诉我该怎么办?

1 个答案:

答案 0 :(得分:2)

阵列非常小 - 只有9个元素。这意味着它的状态不超过9个! = 362880(事实上并非所有的9!都可以,但你可以忽略这一点)。想象一下,你有一个图形,你需要找到从给定顶点(起始位置)到另一个顶点(结束位置或排序数组)的最小边数。现在问题似乎更容易,对吧?一个简单的breadth-first search,你就完成了!现在要解决这个问题,你不必实际构建图形 - 你给出的表示就足够了。使图形的顶点由数组表示,边缘是您可以在给定数组上执行的可能的交换。