# 排序一些苹果！

11

## 问题

``````{5,4}, {8,10}, {2,9}, {13,3}, {11,7}, {6,0}, {12,1}
``````

``````7
``````

``````{5,4}, {8,10}, {2,9}, {13,3}, {11,0}, {6,7}, {12,1}
``````

## 目的

``````{1,2}, {3,4}, {5,6}, {7,8}, {9,10}, {11,12}, {13,0}
``````

``````13, 7, 6, ...
``````

``````{8, 2}, {11, 13}, {3, 12}, {6, 10}, {4, 0}, {1, 7}, {9, 5}
{3, 1}, {6, 9}, {7, 8}, {2, 11}, {10, 5}, {13, 4}, {12, 0}
{0, 2}, {4, 13}, {1, 10}, {11, 6}, {7, 12}, {8, 5}, {9, 3}
{6, 9}, {2, 10}, {7, 4}, {1, 8}, {12, 0}, {5, 11}, {3, 13}
{4, 5}, {10, 3}, {6, 9}, {8, 13}, {0, 2}, {1, 7}, {12, 11}
{4, 2}, {10, 5}, {0, 7}, {9, 8}, {3, 13}, {1, 11}, {6, 12}
{9, 3}, {5, 4}, {0, 6}, {1, 7}, {12, 11}, {10, 2}, {8, 13}
{3, 4}, {10, 9}, {8, 12}, {2, 6}, {5, 1}, {11, 13}, {7, 0}
{10, 0}, {12, 2}, {3, 5}, {9, 11}, {1, 13}, {4, 8}, {7, 6}
{6, 1}, {3, 5}, {11, 12}, {2, 10}, {7, 4}, {13, 8}, {0, 9}
``````

## 规则

• 您的解决方案必须以每次移动的存储桶数的多项式时间运行。关键是要使用巧妙的启发式方法。
• 所有算法必须是确定性的。
• 如果出现平局，则以最短的字节数为准。

2

@JanDvorak每“有什么意义”-好电话。那不是我想到的。我在此定义的合理时间应少于暴力破解解决方案所需的时间；）
Orby 2014年

John Dvorak 2014年

AMK 2014年

4

# 得分：448

``````#1: 62     #6: 40
#2: 32     #7: 38
#3: 46     #8: 50
#4: 50     #9: 54
#5: 40    #10: 36

Total score: 448 moves
``````

# C ++（501字节）

``````#include <cstdio>
#define S(a,b) a=a^b,b=a^b,a=a^b;
int n=14,a[14],i,j,c,g,p,q;
int l(int x){for(j=0;j<n;++j)if(a[j]==x)return j;}
int sw(int d){
p=l(0);q=p+d;
if(a[q]*d>a[q^1]*d)q^=1;
printf("%d,", a[q]);
S(a[q],a[p])
}
int main(){
for(;j<n;scanf("%d", a+j),j++);
for(;++i<n;){
c=l(i)/2;g=(i-1)/2;
if(c-g){
while(l(0)/2+1<c)sw(2);
while(l(0)/2>=c)sw(-2);
while(l(i)/2>g){sw(2);if(l(i)/2>g){sw(-2);sw(-2);}}
}
}
}
``````

1

feersum

@feersum你说得对。刚开始时，我有更多的C ++特定代码，但是在那之后，考虑到切换到C，看来我摆脱了它。
yasen 2014年

Orby

2

## C，426 448

``````#1: 62    #6: 40
#2: 32    #7: 38
#3: 46    #8: 50
#4: 50    #9: 54
#5: 40    #10: 36
``````

``````8 2 11 13 3 12 6 10 4 0 1 7 9 5
``````

``````#define N 7
#define F(x,y) for(y=0;y<N*2;y++)if(A[y]==x)break;
#define S(x,y) x=x^y,y=x^y,x=x^y;
#define C(x,y) ((A[x*2]==y)||(A[x*2+1]==y))
A[N*2],i,j,d,t,b,a,n,s,v,u,w,g;main(){for(;i<N*2;i++)scanf("%d",A+i);g=1;while
(!v){F(0,i);b=i/2;F(g,u);w=u/2;d=b<w?1:-1;n=(b+d)*2;a=(b+d)*2+1;if(A[n]>A[a])
S(n,a);t=d-1?a:n;printf("%d,",A[t]);S(A[i],A[t]);while(C((g-1)/2,g))g++;v=1;for
(j=0;j<N*2;j++)if(!C(j/2,(j+1)%(N*2)))v=0;}}
``````

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

#define N 7

int apples[N*2];

int find(int apple)
{
int i;
for (i = 0; i < N*2; i++) {
if (apples[i] == apple)
return i;
}
}

void swap(int i, int j)
{
int temp;
temp = apples[i];
apples[i] = apples[j];
apples[j] = temp;
}

int contains(int bucket, int apple)
{
if ((apples[bucket * 2] == apple) || (apples[bucket * 2 + 1] == apple))
return 1;
return 0;
}

int is_solved()
{
int i, j;
for (i = 0; i < N * 2; i++) {
j = (i + 1) % (N * 2);
if (!contains(i / 2, j))
return 0;
}
return 1;
}

int main()
{
int i, j, dir, bucket, max, min, score;
int target_i, target_bucket, target;

for (i = 0; i < N*2; i++) {
scanf("%d ", apples + i);
}

target = 1;
while (1) {

i = find(0);
bucket = i / 2;
target_i = find(target);
target_bucket = target_i / 2;

/* Change the direction of the sort if neccesary */
if (bucket < target_bucket) dir = 1;
else dir = -1;

/* Find the biggest and smallest apple in the next bucket */
if (apples[(bucket + dir) * 2] < apples[(bucket + dir) * 2 + 1]) {
min = (bucket + dir) * 2;
max = (bucket + dir) * 2 + 1;
} else {
min = (bucket + dir) * 2 + 1;
max = (bucket + dir) * 2;
}

/* If we're going right, move the smallest apple. Otherwise move the
biggest apple */
if (dir == 1) {
printf("%d, ", apples[min]);
swap(i, min);
score++;
} else {
printf("%d, ", apples[max]);
swap(i, max);
score++;
}

/* Find the next apple to sort */
while (contains((target - 1) / 2, target))
target++;

/* If we've solved it then quit */
if (is_solved())
break;
}
printf("\n");
printf("%d\n", score);
}
``````

2

# Python 3-121

``````c:\python33\python.exe apples.py 7 3 4 10 9 8 12 2 6 5 1 11 13 7 0
``````

``````import sys

BUCKETS = int(sys.argv[1])

# cleans a state up so it is in order
def compressState(someState):
for i in range(BUCKETS):
if(someState[2*i] > someState[2*i + 1]):
temp = someState[2*i]
someState[2*i] = someState[2*i + 1]
someState[2*i + 1] = temp
return someState

state = compressState([int(x) for x in sys.argv[2:]])
print('Starting to solve', state)
WINNINGSTATE = [x for x in range(1, BUCKETS*2 - 1)]
WINNINGSTATE.append(0)
WINNINGSTATE.append(BUCKETS*2 - 1)
maxDepth = 1
winningMoves = []
triedStates = {}

# does a depth-first search
def doSearch(curState, depthLimit):
if(curState == WINNINGSTATE):
return True
if(depthLimit == 0):
return False
myMoves = getMoves(curState)
statesToVisit = []
for move in myMoves:
newState = applyMove(curState, move)
tns = tuple(newState)
# do not visit a state again unless it is at a higher depth (more chances to win from it)
if(not ((tns in triedStates) and (triedStates[tns] >= depthLimit))):
triedStates[tns] = depthLimit
statesToVisit.append((move, newState[:], stateScore(newState)))
statesToVisit.sort(key=lambda stateAndScore: stateAndScore[2])
for stv in statesToVisit:
if(stv[2] > statesToVisit[0][2]):
continue
if(doSearch(stv[1], depthLimit - 1)):
winningMoves.insert(0, stv[0])
return True
return False

# gets the moves you can make from a given state
def getMoves(someState):
# the only not-allowed moves involve the bucket with the 0
allowedMoves = []
for i in range(BUCKETS):
if((someState[2*i] != 0) and (someState[2*i + 1] != 0)):
allowedMoves.append(someState[2*i])
allowedMoves.append(someState[2*i + 1])
return allowedMoves

# applies a move to a given state, returns a fresh copy of the new state
def applyMove(someState, aMove):
newState = someState[:]
for i in range(BUCKETS*2):
if(newState[i] == 0):
zIndex = i
if(newState[i] == aMove):
mIndex = i
if(mIndex % 2 == 0):
newState[mIndex] = 0
else:
newState[mIndex] = newState[mIndex-1]
newState[mIndex-1] = 0
newState[zIndex] = aMove
if((zIndex % 2 == 0) and (newState[zIndex] > newState[zIndex+1])):
newState[zIndex] = newState[zIndex+1]
newState[zIndex+1] = aMove
return newState

# a heuristic for how far this state is from being sorted
def stateScore(someState):
return sum([1 if someState[i] != WINNINGSTATE[i] else 0 for i in range(BUCKETS*2)])

# go!
while(True):
triedStates[tuple(state)] = maxDepth
print('Trying depth', maxDepth)
if(doSearch(state, maxDepth)):
print('winning moves are: ', winningMoves)
break
maxDepth += 1
``````

Orby 2014年

Orby 2014年

RT