题目链接在此
这题做出来破费周折,以至于不想详细写思路了,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; }