Sicily 1041. Pushing Boxes

题目链接在此


这题做出来破费周折,以至于不想详细写思路了,po出来就当是给自己的辛勤与愚昧做个纪念吧。

下面的是自己写的代码,最没必要的是给每个箱子分配变量来跟踪。


当然更推荐这位大神的代码,简单又容易理解。


#include<iostream>
#include<string>
#include<algorithm>

using namespace std;

struct box {  //  top~[0,width-1] left~[0,length-1]
	int top, left;
	int boxesToBottom, boxesToTop, boxesToRight, boxesToLeft;

	box() {}
	box(int t, int l) : top(t), left(l), boxesToBottom(0), boxesToTop(0), boxesToRight(0), boxesToLeft(0){}
};

bool AsdCmpBytop(box a, box b) {
	return (a.top < b.top) || (a.top == b.top && a.boxesToBottom > b.boxesToBottom);
}

bool DesdCmpBytop(box a, box b) {
	return (a.top > b.top) || (a.top == b.top && a.boxesToTop > b.boxesToTop);
}

bool AsdCmpByleft(box a, box b) {
	return (a.left < b.left) || (a.left == b.left && a.boxesToRight > b.boxesToRight);
}

bool DesdCmpByleft(box a, box b) {
	return (a.left > b.left) || (a.left == b.left && a.boxesToLeft > b.boxesToLeft);
}

void stat(box* boxes, int boxNum, bool space[][21], int width,int length) {
	for (int i = 0; i < boxNum; i++) {
		boxes[i].boxesToTop = boxes[i].boxesToBottom = boxes[i].boxesToLeft = boxes[i].boxesToRight = 0;

		for (int j = 0; j < boxes[i].top; j++)
			if (space[j][boxes[i].left] == true)
				boxes[i].boxesToTop++;

		for (int j = boxes[i].top + 1; j < width; j++)
			if (space[j][boxes[i].left] == true)
				boxes[i].boxesToBottom++;

		for (int j = 0; j < boxes[i].left; j++)
			if (space[boxes[i].top][j] == true)
				boxes[i].boxesToLeft++;

		for (int j = boxes[i].left + 1; j < length; j++)
			if (space[boxes[i].top][j] == true)
				boxes[i].boxesToRight++;
	}
}

int main() {
	int caseCount = 1;
	int width, length;
	int boxNum;
	int distFromTop, distFromLeft;
	box boxes[10];
	string op;
	int step;

	while (cin >> width >> length, width && length) {
		bool space[21][21] = { false };  //  是否占用

		cin >> boxNum;
		for (int i = 0; i < boxNum; i++) {
			cin >> distFromTop >> distFromLeft;
			space[distFromTop][distFromLeft] = true;
			boxes[i] = box(distFromTop, distFromLeft);
		}

		while (cin >> op && op != "done") {
			cin >> step;
			
			if (op == "down") {
				step = step < width ? step : width;

				for (int i = 0; i < step; i++) {  //  每一步往下推
					stat(boxes, boxNum, space, width, length);
					sort(boxes, boxes + boxNum, AsdCmpBytop);  //  按到上面的墙距离排升序
					bool movable = true;
					for (int j = 0; j < boxNum; j++) {
						if (boxes[j].top == i) {  //  找到最上面被推的箱子
							int colNum = boxes[j].left;
							int firstEmpty;
							for (firstEmpty = boxes[j].top; firstEmpty < width; firstEmpty++) {
								if (space[firstEmpty][colNum] == false) {  //  自上往下找第一个该列的空位
									for (int k = firstEmpty - 1; k >= boxes[j].top; k--) {
										for (int l = 0; l < boxNum; l++) {
											if (boxes[l].top == k && boxes[l].left == colNum) {
												boxes[l].top = k + 1;
												space[k][colNum] = false;
												space[k+1][colNum] = true;
											}
										}
									}
									break;
								}
							}
							if (firstEmpty >= width) {
								movable = false;
								break;
							}
						}
					}
					if (!movable)
						break;
				}
			}

			else if (op == "up") {
				step = step < width ? step : width;

				for (int i = width - 1; i >= width - step; i--) {  //  每一步往上推
					stat(boxes, boxNum, space, width, length);
					sort(boxes, boxes + boxNum, DesdCmpBytop);
					bool movable = true;
					for (int j = 0; j < boxNum; j++) {
						if (boxes[j].top == i) {  //  找到最下面被推的箱子
							int colNum = boxes[j].left;
							int firstEmpty;
							for (firstEmpty = boxes[j].top; firstEmpty >= 0; firstEmpty--) {
								if (space[firstEmpty][colNum] == false) {  //  自下往上找第一个该列的空位
									for (int k = firstEmpty + 1; k <= boxes[j].top; k++) {
										for (int l = 0; l < boxNum; l++) {
											if (boxes[l].top == k && boxes[l].left == colNum) {
												boxes[l].top = k - 1;
												space[k][colNum] = false;
												space[k - 1][colNum] = true;
											}
										}
									}
									break;
								}
							}
							if (firstEmpty < 0) {
								movable = false;
								break;
							}
						}
					}
					if (!movable)
						break;
				}
			}

			else if (op == "right") {
				step = step < length ? step : length;

				for (int i = 0; i < step; i++) {  //  每一步往右推
					stat(boxes, boxNum, space, width, length);
					sort(boxes, boxes + boxNum, AsdCmpByleft);
					bool movable = true;
					for (int j = 0; j < boxNum; j++) {
						if (boxes[j].left == i) {  //  找到最左边被推的箱子
							int rowNum = boxes[j].top;
							int firstEmpty;
							for (firstEmpty = boxes[j].left; firstEmpty < length; firstEmpty++) {
								if (space[rowNum][firstEmpty] == false) {  //  自左往右找第一个该行的空位
									for (int k = firstEmpty - 1; k >= boxes[j].left; k--) {
										for (int l = 0; l < boxNum; l++) {
											if (boxes[l].left == k && boxes[l].top == rowNum) {
												boxes[l].left = k + 1;
												space[rowNum][k] = false;
												space[rowNum][k + 1] = true;
											}
										}
									}
									break;
								}
							}
							if (firstEmpty >= length) {
								movable = false;
								break;
							}
						}
					}
					if (!movable)
						break;
				}
			}

			else if (op == "left") {
				step = step < length ? step : length;

				for (int i = length - 1; i >= length - step; i--) {  //  每一步往左推
					stat(boxes, boxNum, space, width, length);
					sort(boxes, boxes + boxNum, DesdCmpByleft);
					bool movable = true;
					for (int j = 0; j < boxNum; j++) {
						if (boxes[j].left == i) {  //  找到最右边被推的箱子
							int rowNum = boxes[j].top;
							int firstEmpty;
							for (firstEmpty = boxes[j].left; firstEmpty >= 0; firstEmpty--) {
								if (space[rowNum][firstEmpty] == false) {  //  自右往左找第一个该行的空位
									for (int k = firstEmpty + 1; k <= boxes[j].left; k++) {
										for (int l = 0; l < boxNum; l++) {
											if (boxes[l].left == k && boxes[l].top == rowNum) {
												boxes[l].left = k - 1;
												space[rowNum][k] = false;
												space[rowNum][k - 1] = true;
											}
										}
									}
									break;
								}
							}
							if (firstEmpty < 0) {
								movable = false;
								break;
							}
						}
					}
					if (!movable)
						break;
				}
			}
		}

		cout << "Data set " << caseCount++ << " ends with boxes at locations";		
		for (int i = 0; i < width; i++)
			for (int j = 0; j < length; j++)
				if (space[i][j] == true)
					cout << " (" << i << ',' << j << ')';
		cout << ".\n";
	}

	return 0;
}


你可能感兴趣的:(sicily)