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