QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#39733#2932. Checker SlideLangdao_ZhangAC ✓19ms22912kbC++8.7kb2022-07-13 09:31:322022-07-13 09:31:33

Judging History

你现在查看的是最新测评结果

  • [2023-08-10 23:21:45]
  • System Update: QOJ starts to keep a history of the judgings of all the submissions.
  • [2022-07-13 09:31:33]
  • 评测
  • 测评结果:AC
  • 用时:19ms
  • 内存:22912kb
  • [2022-07-13 09:31:32]
  • 提交

answer

/*
 * Checker Slide
 * Author: Fred Pickel
 * ICPC GNYR 2021 Regional Contest
 * 
 * This is basically a breadth first search problem with big data
 *
 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
//#define DEBUG
//#define TEST
//#define	SHOWS

typedef unsigned int DWORD;
typedef unsigned char BYTE;

#define MIN_CARD 4
#define MAX_CARD 20
char inbuf[256];

typedef struct _slide_pos_
{
	DWORD level;
	DWORD qNext;
	DWORD pathPrev;
} SLIDEPOS, *PSLIDEPOS;

typedef struct _pos_loc_
{
	BYTE chks[4];
} POS_LOC;

#define	POS_CNT (36*36*36*36)

/* This is absolutely terrible. */
#define FLAG (0xffffffff)

SLIDEPOS posTbl[POS_CNT];

int AddrToPos(DWORD addr, POS_LOC *ppos)
{
	ppos->chks[3] = (BYTE)(addr %36);
	addr = addr/36;
	ppos->chks[2] = (BYTE)(addr %36);
	addr = addr/36;
	ppos->chks[1] = (BYTE)(addr %36);
	addr = addr/36;
	ppos->chks[0] = (BYTE)(addr %36);
	return 0;
}

int GetAddr(POS_LOC pos, DWORD *pAddr)
{
	DWORD res;
	int i, j;
	BYTE t;

	// sort in decreasing order
	for(j = 2; j >= 0; j--) {
		for(i = 0; i <= j; i++) {
			if(pos.chks[i] < pos.chks[i+1]) {
				t = pos.chks[i];
				pos.chks[i] = pos.chks[i+1];
				pos.chks[i+1] = t;
			} else if(pos.chks[i] == pos.chks[i+1]){ // invalid
				return -11;
			}
		}
	}
	res = pos.chks[0];
	res = res*36 + pos.chks[1];
	res = res*36 + pos.chks[2];
	res = res*36 + pos.chks[3];
	*pAddr = res;
	return 0;
}


int StrToAddr(const char *str, DWORD *pAddr)
{
	int i, rowcol[8];
	POS_LOC pos;
	if(sscanf(str, "%d %d %d %d %d %d %d %d",
		&rowcol[0], &rowcol[1], &rowcol[2], &rowcol[3], 
		&rowcol[4], &rowcol[5], &rowcol[6], &rowcol[7]) != 8) {
		fprintf(stderr, "Bad scan of input data\n");
		return -21;
	}
	for(i = 0; i < 4; i++) {
		pos.chks[i] = 6*rowcol[2*i] + rowcol[2*i+1];
	}
	return GetAddr(pos, pAddr);
}

int AddrToStr(DWORD addr, char *pres)
{
	int i, rowcol[8];
	for(i = 7; i >= 0 ; i--) {
		rowcol[i] = addr % 6;
		addr /= 6;
	}
	sprintf(pres, "%d%d%d%d%d%d%d%d",
		rowcol[0], rowcol[1], rowcol[2], rowcol[3], 
		rowcol[4], rowcol[5], rowcol[6], rowcol[7]);
	return 0;
}

DWORD startAddr, endAddr, qHead, qTail, maxLevel;
int nSolnSteps, bSolution;

int GenMoves(DWORD curAddr)
{
	POS_LOC pos, newpos;
	BYTE rowcol[8], bd[6][6], val, currow, curcol, row, col;
	int i, j, ret;
	DWORD addr, level;
	level = posTbl[curAddr].level + 1;
	AddrToPos(curAddr, &pos);

	memset(&(bd[0][0]), '\0', sizeof(bd));

	for(i = 0; i < 4; i++) {
		val = pos.chks[i];
		rowcol[2*i+1] = val %6;
		rowcol[2*i] = val/6;
		bd[val/6][val %6] = 1;
	}
	// now find moves up to 4 per piece
	for(i = 0; i < 4; i++) {
		currow = rowcol[2*i];
		curcol = rowcol[2*i+1];
		// up?
		if((currow > 0) && (bd[currow - 1][curcol] == 0)){
			newpos = pos;
			col = curcol;
			row = 0;
			for(j = currow - 1; j >= 0 ; j--) {
				if(bd[j][col] != 0) {
					row  = j+1;
					break;
				}
			}
			newpos.chks[i] = row*6 + col;
			if((ret = GetAddr(newpos, &addr)) != 0) {
				return -31;
			}
			if(endAddr == addr) {	// found it
				posTbl[addr].pathPrev = curAddr;
				return level;
			}
			if(posTbl[addr].level == FLAG) {	// not already seen
				posTbl[qTail].qNext = addr;
				qTail = addr;
				posTbl[addr].level = level;
				posTbl[addr].pathPrev = curAddr;
			}
		}
		// down?
		if((currow < 5) && (bd[currow + 1][curcol] == 0)){
			newpos = pos;
			col = curcol;
			row = 5;
			for(j = currow + 1; j <= 5 ; j++) {
				if(bd[j][col] != 0) {
					row  = j-1;
					break;
				}
			}
			newpos.chks[i] = row*6 + col;
			if((ret = GetAddr(newpos, &addr)) != 0) {
				return -32;
			}
			if(endAddr == addr) {	// found it
				posTbl[addr].pathPrev = curAddr;
				return level;
			}
			if(posTbl[addr].level == FLAG) {	// not already seen
				posTbl[qTail].qNext = addr;
				qTail = addr;
				posTbl[addr].level = level;
				posTbl[addr].pathPrev = curAddr;
			}
		}
		// left?
		if((curcol > 0) && (bd[currow][curcol-1] == 0)){
			newpos = pos;
			col = 0;
			row = currow;
			for(j = curcol - 1; j >= 0 ; j--) {
				if(bd[row][j] != 0) {
					col  = j+1;
					break;
				}
			}
			newpos.chks[i] = row*6 + col;
			if((ret = GetAddr(newpos, &addr)) != 0) {
				return -33;
			}
			if(endAddr == addr) {	// found it
				posTbl[addr].pathPrev = curAddr;
				return level;
			}
			if(posTbl[addr].level == FLAG) {	// not already seen
				posTbl[qTail].qNext = addr;
				qTail = addr;
				posTbl[addr].level = level;
				posTbl[addr].pathPrev = curAddr;
			}
		}
		// rt?
		if((curcol < 5) && (bd[currow][curcol + 1] == 0)){
			newpos = pos;
			col = 5;
			row = currow;
			for(j = curcol + 1; j <= 5 ; j++) {
				if(bd[row][j] != 0) {
					col  = j-1;
					break;
				}
			}
			newpos.chks[i] = row*6 + col;
			if((ret = GetAddr(newpos, &addr)) != 0) {
				return -34;
			}
			if(endAddr == addr) {	// found it
				posTbl[addr].pathPrev = curAddr;
				return level;
			}
			if(posTbl[addr].level == FLAG) {	// not already seen
				posTbl[qTail].qNext = addr;
				qTail = addr;
				posTbl[addr].level = level;
				posTbl[addr].pathPrev = curAddr;
			}
		}
	}
	return 0;
}


int Solve()
{
	DWORD curAddr;
	int lev;
	DWORD newlev;
	memset(&(posTbl[0]), 0xff, POS_CNT*sizeof(SLIDEPOS));
	curAddr = startAddr;
	posTbl[curAddr].level = 0;
	qHead = qTail = curAddr;
	lev = 0;
	newlev = 0;
	bSolution = 0;
	while((lev == 0) && (qHead != FLAG)) {
		lev = GenMoves(qHead);
		qHead = posTbl[qHead].qNext;
		if(qHead != FLAG) {
			if(posTbl[qHead].level != newlev) {
				newlev = posTbl[qHead].level;
//				printf("lev %d\r\n", newlev);
			}
			if(newlev > maxLevel) {
				return newlev;
			}
		}

	}
	if(lev > 0) {
		nSolnSteps = lev;
		bSolution = 1;
	}
	return lev;
}

void ShowDiffs(char *s1, char *s2)
{
	int i, j;
	unsigned char uc1 = 0, uc2 = 0;

	for(i = 0; i < 8; i += 2){
		for(j = 0; j < 8; j += 2){
			if(s1[i] == s2[j] && s1[i+1] == s2[j+1]){
				uc1 |= (1<<(i/2));
				uc2 |= (1<<(j/2));
			}
		}
	}
#ifdef DEBUG
	printf("uc1=%x uc2=%x\n", uc1, uc2);
#endif
	for(i = 0; i < 4; i++){
		if((uc1 & (1<<i)) == 0){
			printf("%c %c ", s1[i*2], s1[i*2+1]);
			break;
		}
	}
	for(i = 0; i < 4; i++){
		if((uc2 & (1<<i)) == 0){
			printf("%c %c\n", s2[i*2], s2[i*2+1]);
			break;
		}
	}
}

void ShowSoln(char *szStart, int cnt)
{
	char *p;
	char **addrs;
	DWORD curAddr;
	int idx = cnt;

	addrs = new char *[cnt];
	if(addrs == NULL){
		fprintf(stderr, "memory alloc error in show soln\n");
		return;
	}
	
	curAddr = endAddr;
	while(curAddr != startAddr) {
		if(idx == 0){
			fprintf(stderr, "count ran out!\n");
			return;
		}
		p = new char[16];
		if(p == NULL){
			fprintf(stderr, "memory alloc error 2 in show soln\n");
			return;
		}
		AddrToStr(curAddr, p);
		addrs[--idx] = p;
		curAddr = posTbl[curAddr].pathPrev;
	}
	if(idx != 0){
		fprintf(stderr, "Extra slots in show soln\n");
		return;
	}
	for(idx = 0; idx < cnt; idx++){
#ifdef DEBUG
		printf("%d: %s %s\n", idx, szStart, addrs[idx]);
#endif
		ShowDiffs(szStart, addrs[idx]);
		if(idx > 0){
			delete [] szStart;
		}
		szStart = addrs[idx];
	}
}

int main()
{
	int ret, cnt;
	char szStart[32];
#ifdef TEST
	int nprob, curprob, probnum, problines;
	if(fgets(&(inbuf[0]), 255, stdin) == NULL) {
		fprintf(stderr, "read failed on problem count\n");
		return -1;
	}
	if(sscanf(&(inbuf[0]), "%d", &nprob) != 1){
		fprintf(stderr, "scan failed on problem count\n");
		return -2;
	}
	for(curprob = 1; curprob <= nprob  ;  curprob++) {
		if(fgets(&(inbuf[0]), 255, stdin) == NULL) {
			fprintf(stderr, "read failed on problem num & sz\n");
			return -3;
		}
		if(sscanf(&(inbuf[0]), "%d %d", &probnum, &problines) != 2){
			fprintf(stderr, "scan failed on num & sz\n");
			return -4;
		}
#endif
	maxLevel = 50;
	if(fgets(&(inbuf[0]), 255, stdin) == NULL) {
		fprintf(stderr, "read failed on start pos\n");
		return -7;
	}
	if((ret = StrToAddr(&(inbuf[0]), &startAddr)) != 0) {
		fprintf(stderr, "scan of start pos ret %d\n", ret);
		return -8;
	}
	if(fgets(&(inbuf[0]), 255, stdin) == NULL) {
		fprintf(stderr, "read failed on end pos\n");
		return -7;
	}
	if((ret = StrToAddr(&(inbuf[0]), &endAddr)) != 0) {
		fprintf(stderr, "scan of end pos ret %d\n", ret);
		return -10;
	}
	cnt = Solve();
#ifdef TEST
	printf("%d: %d\n", curprob, cnt);
	if((cnt > 0) && (cnt < (int)maxLevel)) {
		ShowSoln(cnt);
	}
	}
#else
	if(bSolution){
		printf("%d\n", cnt);
		if((cnt > 0) && (cnt < (int)maxLevel)) {
			AddrToStr(startAddr, &(szStart[0]));
			ShowSoln(szStart, cnt);
		}
	} else {
		printf("no solution in %d levels\n", maxLevel);
	}
#endif
	return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 4ms
memory: 22812kb

input:

5 5 5 0 0 5 0 0
2 2 2 1 1 2 1 1

output:

12
5 0 1 0
0 5 4 5
0 0 0 5
4 5 1 5
5 5 2 5
1 5 1 1
0 5 1 5
1 5 1 2
1 1 5 1
1 0 1 1
5 1 2 1
2 5 2 2

result:

ok correct plan

Test #2:

score: 0
Accepted
time: 19ms
memory: 22912kb

input:

3 2 2 1 1 0 0 3
4 3 3 5 1 3 0 4

output:

18
3 2 5 2
2 1 2 5
2 5 5 5
5 5 5 3
5 3 1 3
5 2 5 0
1 0 4 0
0 3 0 0
0 0 3 0
4 0 4 5
5 0 4 0
4 0 4 4
4 5 5 5
5 5 5 0
5 0 4 0
4 0 4 3
4 4 0 4
3 0 3 5

result:

ok correct plan

Test #3:

score: 0
Accepted
time: 9ms
memory: 22832kb

input:

5 5 3 4 2 0 0 2
3 4 3 0 0 2 0 1

output:

4
5 5 5 0
5 0 3 0
2 0 0 0
0 0 0 1

result:

ok correct plan

Test #4:

score: 0
Accepted
time: 2ms
memory: 22712kb

input:

3 5 2 1 1 5 0 3
2 2 1 3 1 2 0 1

output:

6
3 5 2 5
2 5 2 2
2 1 0 1
0 3 0 2
0 2 1 2
1 5 1 3

result:

ok correct plan

Test #5:

score: 0
Accepted
time: 3ms
memory: 22796kb

input:

2 2 1 5 0 3 0 1
2 2 1 4 0 3 0 1

output:

8
0 3 0 2
0 2 1 2
1 2 1 4
1 5 0 5
0 5 0 2
0 2 1 2
1 2 1 3
1 3 0 3

result:

ok correct plan

Test #6:

score: 0
Accepted
time: 2ms
memory: 22796kb

input:

5 0 4 5 3 0 1 0
4 4 4 0 3 5 1 0

output:

6
5 0 4 0
4 0 4 4
4 5 5 5
5 5 5 0
5 0 4 0
3 0 3 5

result:

ok correct plan

Test #7:

score: 0
Accepted
time: 9ms
memory: 22828kb

input:

5 3 4 3 1 4 1 2
3 4 3 2 2 2 0 1

output:

18
5 3 5 0
5 0 0 0
1 4 1 3
1 3 3 3
4 3 4 0
1 2 0 2
0 0 3 0
3 0 3 2
4 0 0 0
3 3 3 5
0 0 0 1
0 2 2 2
3 2 3 4
3 5 5 5
0 1 5 1
5 5 5 2
5 2 3 2
5 1 0 1

result:

ok correct plan

Test #8:

score: 0
Accepted
time: 9ms
memory: 22812kb

input:

1 5 1 4 1 3 1 0
5 3 5 2 3 4 3 1

output:

20
1 5 5 5
1 3 5 3
5 5 5 4
5 4 2 4
1 4 1 1
1 0 5 0
5 3 5 1
5 1 2 1
1 1 1 5
1 5 5 5
5 5 5 1
5 1 3 1
5 0 5 5
2 1 2 3
2 3 5 3
5 5 5 4
5 4 3 4
2 4 2 0
2 0 5 0
5 0 5 2

result:

ok correct plan

Test #9:

score: 0
Accepted
time: 7ms
memory: 22836kb

input:

3 4 3 3 3 1 2 3
5 1 1 4 1 1 0 2

output:

16
3 4 0 4
3 3 5 3
5 3 5 5
3 1 0 1
2 3 5 3
5 5 5 4
5 4 1 4
5 3 5 0
0 4 0 2
0 2 5 2
5 0 5 1
5 1 1 1
0 1 0 0
0 0 5 0
5 0 5 1
5 2 0 2

result:

ok correct plan

Test #10:

score: 0
Accepted
time: 2ms
memory: 22808kb

input:

3 2 2 0 0 2 0 1
2 1 1 0 0 2 0 1

output:

5
0 2 2 2
2 0 2 1
2 2 0 2
3 2 1 2
1 2 1 0

result:

ok correct plan

Test #11:

score: 0
Accepted
time: 4ms
memory: 22824kb

input:

3 2 3 1 2 3 0 4
3 2 1 2 0 3 0 2

output:

6
3 1 0 1
0 4 0 2
2 3 0 3
0 2 2 2
0 1 0 2
2 2 1 2

result:

ok correct plan

Test #12:

score: 0
Accepted
time: 1ms
memory: 22808kb

input:

3 1 2 3 1 2 0 2
5 0 2 1 1 2 1 1

output:

6
2 3 2 0
0 2 0 0
2 0 1 0
1 0 1 1
3 1 2 1
0 0 5 0

result:

ok correct plan

Test #13:

score: 0
Accepted
time: 3ms
memory: 22808kb

input:

3 3 3 1 2 3 0 4
2 0 1 5 1 0 0 3

output:

7
3 1 3 0
0 4 0 0
3 0 1 0
2 3 2 0
3 3 0 3
1 0 1 5
0 0 1 0

result:

ok correct plan

Test #14:

score: 0
Accepted
time: 9ms
memory: 22836kb

input:

3 1 2 2 1 3 0 1
4 4 3 2 2 3 0 0

output:

18
3 1 1 1
2 2 5 2
1 1 1 2
1 3 0 3
1 2 4 2
0 1 0 2
0 2 3 2
4 2 4 5
5 2 4 2
4 2 4 4
4 5 0 5
0 5 0 4
0 4 3 4
3 4 3 3
0 3 2 3
3 3 5 3
5 3 5 0
5 0 0 0

result:

ok correct plan

Test #15:

score: 0
Accepted
time: 3ms
memory: 22824kb

input:

5 3 3 1 2 5 2 4
3 4 0 4 0 2 0 1

output:

7
3 1 0 1
2 5 5 5
5 5 5 4
5 4 3 4
5 3 0 3
2 4 0 4
0 3 0 2

result:

ok correct plan