동전 이동 게임 의 풀이 알고리즘
5538 단어 데이터 구조 와 알고리즘
동전 5 개, 정면 3 개, 뒷면 2 개가 있 는데 처음에는 간격 으로 배열 되 어 있 었 다. 그림 1 참조.
그림. 1 다섯 개의 동전 의 원시 배열
이동 할 때마다 서로 다른 동전 2 개 만 이동 할 수 있 습 니 다. 즉, 이동 하 는 동전 두 개 는 반드시 하 나 는 정면 이 고 하 나 는 뒷면 이 며 두 개의 동전 은 서로 인접 해 있 습 니 다. 왼쪽 이나 오른쪽으로 이동 할 수 있 지만 이동 하 는 방향 에는 반드시 인접 한 동전 이 있어 야 합 니 다. 이동 할 때 는 인접 한 동전 을 건 너 야 합 니 다. 예 를 들 어 1, 2 개의 동전 은 오른쪽으로 이동 할 수 있 습 니 다.그러나 왼쪽으로 이동 하면 안 됩 니 다. 왼쪽 에 인접 한 동전 이 없 기 때 문 입 니 다. 오른쪽으로 이동 할 때 오른쪽 에 서로 붙 어 있 는 모든 동전 을 건 너 야 합 니 다. 그림 2 참조.
그림. 2 앞의 두 동전 을 이동 합 니 다.
이동 방향 에서 동전 이 연속 되 지 않 으 면 동전 을 넣 을 수 있 는 첫 번 째 곳 으로 만 이동 할 수 있다. 예 를 들 어 아래 의 예 를 들 어 왼쪽 에서 세 번 째, 네 번 째 동전 을 왼쪽으로 이동 하려 면 중간 빈자리 로 만 이동 할 수 있 고 빈 자 리 를 건 너 뛰 어 맨 왼쪽으로 이동 할 수 없다. 그림 3 참조.
그림. 3 또 다른 이동 예
최종 목 표 는 바로 한쪽 으로 이동 하고 반대 쪽 으로 이동 하 는 것 이다.
그림. 4 최종 목표
이 문 제 는 보기 에는 매우 간단 한 것 같 지만, 실제로 해 보 니 여전히 매우 어렵 다 는 것 을 알 게 되 었 다. 나 는 오랫동안 시험 해 보고 나 서 야 답 을 찾 았 다.
그러나 이 문 제 는 컴퓨터 로 계산 하 는 것 이 어렵 지 않 고 재 귀 알고리즘 으로 계산 하기에 매우 적합 합 니 다. 다음은 제 가 작성 한 프로그램 입 니 다. 이 프로그램의 계 산 량 이 많 지 않 기 때문에 계산 효율 문 제 를 고려 하지 않 고 프로그램 을 가능 한 한 간단 하고 직 설 적 으로 만 듭 니 다.
프로그램 에서 이 동전 들 의 정 보 를 문자열 로 저장 합 니 다. "A" 긍정 적 반면, 빈 칸 은 빈 자 리 를 표시 합 니 다. 따라서 문자열 은 다음 과 같이 초기 화 됩 니 다. ABABA "。동전 을 옮 기 는 데 대응 하 는 것 은 문자열 의 AB 위 치 를 바 꾸 는 것 입 니 다. 동전 을 옮 기 는 동작 은 move 에 있 습 니 다. 함수 함수 에 정형 매개 변수 가 들 어 옵 니 다. i. 현재 움 직 이 는 동전 이 어느 두 개 인지, 왼쪽으로 움 직 이 는 지, 오른쪽으로 움 직 이 는 지 표시 합 니 다. 구체 적 인 방법 은 i 의 가장 낮은 bit 입 니 다. 옮기다 짝수 일 때 는 왼쪽으로 움 직 이 는 것 을 나타 내 고, i 는 홀수 일 때 는 오른쪽으로 동전 을 움 직 이 는 것 을 나타 낸다. 나머지 비트 현재 이동 하고 있 는 동전 이 두 개 인지 표시 합 니 다. Move 함수 의 반환 값 은 이번 이동 이 성 공 했 는 지 여 부 를 표시 합 니 다.
구체 적 인 코드 는 다음 과 같다.
static bool move(string &coins, int i)
{
int dir = i % 2; // 0 ,1
i = i / 2;
if(coins[i] == ' ' || coins[i + 1] == ' ' || coins[i] == coins[i + 1])
{
return false; //
}
if( dir == 0 ) //
{
if( coins[ i - 1] == ' ') // ,
{
return false;
}
else
{
string::size_type j = i - 2;
while( coins[j] != ' ' && j > 1) {j --;}
coins[j - 1] = coins[i];
coins[j] = coins[i + 1];
coins[i] = ' ';
coins[i + 1] = ' ';
}
}
else
{
if( coins[i + 2] == ' ') // ,
{
return false;
}
else
{
string::size_type j = i + 3;
while(coins[j] != ' ' && j < coins.size() - 1) {j ++;}
coins[j] = coins[i];
coins[j + 1] = coins[i + 1];
coins[i] = ' ';
coins[i + 1] = ' ';
}
}
return true;
}
isSeperated 함수 가 동전 을 분리 하 는 지 여 부 를 판단 합 니 다. 알고리즘 은 간단 합 니 다. 분명 더 효율 적 인 알고리즘 이 있 을 것 입 니 다. 저 는 이 위 에 신경 을 많이 쓰 지 않 았 습 니 다. 이 작은 프로그램 에 있어 서 프로그램 을 쓰 는 데 걸 리 는 시간 이 프로그램 이 실행 하 는 시간 보다 훨씬 많 을 것 입 니 다. 그래서 제 가 추구 하 는 것 은 이 프로그램 을 어떻게 빨리 쓰 느 냐 가 아니 라 어떻게 빨리 달 릴 수 있 느 냐 입 니 다. 다음은 세대 입 니 다.코드:
static bool isSeperated(string coins)
{
int first = 0, last = coins.size() - 1;
while(coins[first] == ' ') {first ++;} //
while(coins[last] == ' ') {last --;} //
if(coins[first] == coins[last] ) return false;// ,
int i = first + 1, j = last - 1;
while(coins[i] == coins[first] || coins[i] == ' '){i ++;} //
while(coins[j] == coins[last] || coins[j] == ' '){j --;} //
if( i != j + 1) return false;
return true; //
}
Solve 함수 가 계산 을 책임 지고 알고리즘 은 간단 합 니 다. 쉽게 말 하면 궁 거 법 입 니 다. 가능 한 이동 방법 을 모두 시험 해 보면 반드시 정확 한 절 차 를 얻 을 수 있 습 니 다. 유일 하 게 설명 해 야 할 것 은 이 문제 에 대해 이동 할 수 있 는 걸음 수 는 무한 합 니 다. 따라서 검색 깊이 를 제한 하 는 것 입 니 다. 즉, 최대 몇 걸음 을 이동 해 야 궁 거 가 끝 날 수 있 습 니 다. 층수 에 따라(걸음 수) 검색 은 당연히 재 귀 알고리즘 으로 쓰 는 것 이 가장 편리 합 니 다. 다음은 코드 입 니 다.
bool solve(string coins, int depth)
{
string coins2 = coins;
int first = 0;
int last = coins.size() - 1;
while(coins[first] == ' ') {first ++;}
while(coins[last] == ' ') {last --;}
for( int i = 2 * first; i < 2 * (last - 1); i++ )
{
if( move(coins, i) )
{//
depth --; //
if( isSeperated(coins) )
{
// ,
cout << coins << endl;
return true;
}
else if( depth != 0 && solve(coins, depth) )//
{
cout << coins << endl;
return true;
}
else
{
//
coins = coins2;
depth ++;
continue; //
}
}
}
// ,
return false;
}
마지막 으로 메 인 프로그램 입 니 다. 몇 줄 입 니 다. 더 이상 설명 할 필요 가 없습니다.
int main()
{
string coins(" ABABA ");
if(solve(coins, 5))
{
cout << coins << endl;
}
return 0;
}
프로그램 출력 결 과 는 다음 과 같 습 니 다.
AAABB ABAA B A ABAB AABAB ABAAB ABABA
설명 이 필요 한 것 은 재 귀 이기 때문에 수출 결 과 는 아래 에서 위로 봐 야 한 다 는 것 이다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
[JAVA] 배열 회전 출력요소 가 출력 을 시작 하 는 위치 에 주의 하 십시오. 모두 몇 라운드 의 수출 이 있 습 니까? n/2 + 1 매 라 운 드 는 상, 우, 하, 좌 로 나 뉜 다. 각 방향의 시작 위치 와 좌표 의 관 계 를 구...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.