Task: | Klotski |
Sender: | Game of Nolife |
Submission time: | 2017-05-27 14:16:37 +0300 |
Language: | C++ |
Status: | READY |
Result: | ACCEPTED |
test | verdict | time | |
---|---|---|---|
#1 | ACCEPTED | 0.15 s | details |
#2 | ACCEPTED | 0.10 s | details |
#3 | ACCEPTED | 0.04 s | details |
#4 | ACCEPTED | 0.12 s | details |
#5 | ACCEPTED | 0.12 s | details |
#6 | ACCEPTED | 0.05 s | details |
#7 | ACCEPTED | 0.06 s | details |
#8 | ACCEPTED | 0.06 s | details |
#9 | ACCEPTED | 0.04 s | details |
#10 | ACCEPTED | 0.03 s | details |
#11 | ACCEPTED | 0.07 s | details |
#12 | ACCEPTED | 0.12 s | details |
Code
#include <bits/stdc++.h>#define F first#define S second#define X real()#define Y imag()using namespace std;typedef long long ll;typedef long double ld;typedef pair<int,int> pii;string grid[5];struct state {pii xloc;pii eloc;pii adloc[4];pii filoc[4];state() {}state(pii xx, pii ee, pii* ad, pii* fi) : xloc(xx), eloc(ee) {for (int i=0;i<4;i++) {adloc[i]=ad[i];filoc[i]=fi[i];}sort(adloc,adloc+4);sort(filoc,filoc+4);}bool isSolved() {if (xloc.F == 3 && xloc.S == 1) return true;return false;}bool operator==(const state& ref) const {if (xloc!=ref.xloc) return false;if (eloc!=ref.eloc) return false;for (int i=0;i<4;i++) {if (adloc[i]!=ref.adloc[i]) return false;if (filoc[i]!=ref.filoc[i]) return false;}return true;}bool operator<(const state& ref) const {if (xloc!=ref.xloc) return xloc<ref.xloc;if (eloc!=ref.eloc) return eloc<ref.eloc;for (int i=0;i<4;i++) {if (adloc[i]!=ref.adloc[i]) return adloc[i]<ref.adloc[i];if (filoc[i]!=ref.filoc[i]) return filoc[i]<ref.filoc[i];}return false;}bool isFree(int i, int j) {if (i<0 || i>=5) return false;if (j<0 || j>=4) return false;if (xloc.F == i || xloc.F == i-1) {if (xloc.S == j || xloc.S == j-1) return false;}if (eloc.F == i) {if (eloc.S == j || eloc.S == j-1) return false;}for (int ii=0;ii<4;ii++) {if (adloc[ii].F == i || adloc[ii].F == i-1) {if (adloc[ii].S == j) return false;}if (filoc[ii].F == i && filoc[ii].S == j) return false;}return true;}int blockInd(int i, int j) {if (i<0 || i>=5) return -1;if (j<0 || j>=4) return -1;if (xloc.F == i || xloc.F == i-1) {if (xloc.S == j || xloc.S == j-1) return 10;}if (eloc.F == i) {if (eloc.S == j || eloc.S == j-1) return 5;}for (int ii=0;ii<4;ii++) {if (adloc[ii].F == i || adloc[ii].F == i-1) {if (adloc[ii].S == j) return ii+1;}if (filoc[ii].F == i && filoc[ii].S == j) return ii+6;}return -1;}bool checkCell(int i, int j, int block) {// cout<<isFree(i,j)<<" "<<blockInd(i,j)<<endl;if (isFree(i,j) || blockInd(i,j)==block) return true;return false;}bool canMove(int block, pii dir) {if (block==10) {if (!checkCell(xloc.F+dir.F,xloc.S+dir.S,block)) return false;if (!checkCell(xloc.F+dir.F+1,xloc.S+dir.S,block)) return false;if (!checkCell(xloc.F+dir.F,xloc.S+dir.S+1,block)) return false;if (!checkCell(xloc.F+dir.F+1,xloc.S+dir.S+1,block)) return false;} else if (block==5) {if (!checkCell(eloc.F+dir.F,eloc.S+dir.S,block)) return false;if (!checkCell(eloc.F+dir.F,eloc.S+dir.S+1,block)) return false;} else if (block<5) {if (!checkCell(adloc[block-1].F+dir.F,adloc[block-1].S+dir.S,block)) return false;if (!checkCell(adloc[block-1].F+dir.F+1,adloc[block-1].S+dir.S,block)) return false;} else {if (!checkCell(filoc[block-6].F+dir.F,filoc[block-6].S+dir.S,block)) return false;}return true;}state move(int block, pii dir) {state s(xloc,eloc,adloc,filoc);if (block==10) {s.xloc.F+=dir.F;s.xloc.S+=dir.S;} else if (block==5) {s.eloc.F+=dir.F;s.eloc.S+=dir.S;} else if (block<5) {s.adloc[block-1].F+=dir.F;s.adloc[block-1].S+=dir.S;} else {s.filoc[block-6].F+=dir.F;s.filoc[block-6].S+=dir.S;}sort(s.adloc,s.adloc+4);sort(s.filoc,s.filoc+4);return s;}};void printState(state pri) {for (int i=0;i<5;i++) {for (int j=0;j<4;j++) {int block=pri.blockInd(i,j);if (block==-1) cout<<".";else if (block==10) cout<<"X";else cout<<(char)(block+'A'-1);}cout<<endl;}}pair<bool,state> moveBlock(state current, int block, pii dir) {// printState(current);// cout<<block<<" "<<dir.F<<" "<<dir.S<<endl;if (block==-1) return {false,current};// cout<<block<<" "<<dir.F<<" "<<dir.S<<endl;if (!current.canMove(block,dir)) return {false,current};// cout<<block<<" "<<dir.F<<" "<<dir.S<<endl;return {true,current.move(block,dir)};}pii aadd[4];pii ffii[4];int bfs(state start) {// printState(start);set<state> visited;vector<pair<state,int>> toHandle;toHandle.push_back({start,0});visited.insert(start);for (unsigned int ii=0;ii<toHandle.size();ii++) {// cout<<ii<<endl;if (toHandle[ii].F.isSolved()) return toHandle[ii].S;state cur=toHandle[ii].F;for (int i=0;i<5;i++) {for (int j=0;j<4;j++) {if (cur.isFree(i,j)) {for (int i2=-1;i2<=1;i2++) {for (int j2=-1;j2<=1;j2++) {if (i2*j2==0 && abs(i2+j2)==1) {auto z = moveBlock(cur,cur.blockInd(i+i2,j+j2),{-i2,-j2});// cout<<"bfs "<<z.F<<" "<<visited.count(z.S)<<endl;// cout<<visited.size()<<endl;if (z.F && !visited.count(z.S)) {visited.insert(z.S);toHandle.push_back({z.S,toHandle[ii].S+1});// cout<<"---"<<endl;// printState(z.S);// cout<<"---"<<endl;}}}}}}}// return -1;}return -1;}int main(){ios_base::sync_with_stdio(0);cin.tie(0);for (int i=0;i<5;i++) cin>>grid[i];map<char,pii> loc;for (int i=0;i<5;i++) {for (int j=0;j<4;j++) {if (grid[i][j]!='.' && !loc.count(grid[i][j])) {loc[grid[i][j]]={i,j};}}}for (char c='A';c<='D';c++) aadd[c-'A']=loc[c];for (char c='F';c<='I';c++) ffii[c-'F']=loc[c];state starting(loc['X'],loc['E'],aadd,ffii);cout<<bfs(starting)<<"\n";}
Test details
Test 1
Verdict: ACCEPTED
input |
---|
AXXC AXXC BEED BGHD F..I |
correct output |
---|
116 |
user output |
---|
116 |
Test 2
Verdict: ACCEPTED
input |
---|
XXAB XXAB CDEE CDFG HI.. |
correct output |
---|
104 |
user output |
---|
104 |
Test 3
Verdict: ACCEPTED
input |
---|
XXEE XXAB CDAB CDFG HI.. |
correct output |
---|
35 |
user output |
---|
35 |
Test 4
Verdict: ACCEPTED
input |
---|
XXFG XXAB CDAB CDEE HI.. |
correct output |
---|
79 |
user output |
---|
79 |
Test 5
Verdict: ACCEPTED
input |
---|
XXFG XXAB CDAB CDHI EE.. |
correct output |
---|
70 |
user output |
---|
70 |
Test 6
Verdict: ACCEPTED
input |
---|
FGHI AXXB AXXB CEED C..D |
correct output |
---|
-1 |
user output |
---|
-1 |
Test 7
Verdict: ACCEPTED
input |
---|
FGHI AEEB AXXB CXXD C..D |
correct output |
---|
1 |
user output |
---|
1 |
Test 8
Verdict: ACCEPTED
input |
---|
FGHI AEEB A..B CXXD CXXD |
correct output |
---|
0 |
user output |
---|
0 |
Test 9
Verdict: ACCEPTED
input |
---|
FXXG AXXB AEEB .CD. HCDI |
correct output |
---|
-1 |
user output |
---|
-1 |
Test 10
Verdict: ACCEPTED
input |
---|
EECD FGCD ..HI BAXX BAXX |
correct output |
---|
5 |
user output |
---|
5 |
Test 11
Verdict: ACCEPTED
input |
---|
..CD FGCD EEHI BAXX BAXX |
correct output |
---|
15 |
user output |
---|
15 |
Test 12
Verdict: ACCEPTED
input |
---|
FXXG CXXD CABD HABI .EE. |
correct output |
---|
100 |
user output |
---|
100 |