USACO算法系列十六(续)

     题目:http://www.nocow.cn/index.php/Translate:USACO/camelot

     昨天晚上写了一个晚上的这道题,各种边界条件和意外情况。看着自己写的600多行代码,和一连串的Test OK.心里特别有成就感,但是看了别人写的代码80几行,就发现了实力的差距。

     先说说自己的想法吧,那个高浓缩的80行代码,我也不想看了。看了也看不懂。

     这道题,相当于,寻找一个集结地,使得所有骑士和国王到达集结地的总步数最少,骑士走‘日’,国王可以往附近相邻的一格,走横、竖、斜,骑士可以带国王走。

     因此,到达集结地最短的方式,有下面几种:

     (1)所有骑士以最短路径到达集结地,并且途中有个骑士带上国王。

     (2)其中有个骑士以最短路径到国王位置带上国王,然后所有骑士以最短路径到达集结地。

     (3)国王以最短路径到最邻近的一个骑士,所有骑士以最短路径到达集结地。

     (4)国王自己走的集结地,所有骑士以最短路径到达集结地。

    为了判断骑士到集结地的途中,能否带上国王,我先以国王为起点遍历到所有骑士距离k【i】(i为第几个骑士),则如果集结地到国王的步数l + 国王到骑士的步数k【i】== 集结地到达骑士i的步数,则说明骑士去集结地的途中能带上国王。如果起初国王的位置上就有骑士,此步可以跳过。则最短距离就是所有骑士到集结地的距离。

     否则根据(2)(3)(4)来求得最短距离。

     (2)为所有骑士到集结地的步数和 + 最小骑士到国王的步数 + 国王到集结地的步数 - 带着国王的骑士到集结地的步数。

     (3)为所有骑士到集结地的步数和 + 国王到最近的骑士的步数

     (4)为所有骑士到集结地的步数和 + 国王到集结地的步数。

     我知道,这个方法很烂,代码像封建社会女人的裹脚布,但是它AC了,我对它都绝望的时候,它AC了,哈哈哈……………………

 #include <iostream> #include <fstream> #include <math.h> #define ROW 31 #define COLUMN 27 #define SIZE 780 #define LARGE 0X7FFFFFFF #define KNIGHT 800 #define KING 900 #define PATHSIZE 800 using namespace std; struct Position { int r; int c; }; //棋盘 int R,C; int grid[ROW][COLUMN] = {0}; //骑士 Position knight[SIZE]; int knightload[SIZE]; //骑士所走过的路的长度 int kl; int result = LARGE; //国王 Position king; int kingtoknight[SIZE]; //骑士到国王的距离 bool flag = false; Position knightk; //国王到最近骑士的距离 int kntok = LARGE;//国王到最近骑士的距离 //记录遍历路径 Position path[PATHSIZE]; int pl = 0; //初始化整个棋盘 void initGrid() { for (int i=1; i <= R; i++) { for (int j=1; j <= C;j ++) { grid[i][j] = 0; }//end j }//end i grid[king.r][king.c] = KING; for (int i =0; i < kl; i ++ ) { grid[knight[i].r][knight[i].c] = KNIGHT; }//end i } int getKnight(int r,int c) { for (int i=0; i < kl; i ++) { if (knight[i].r == r && knight[i].c == c) { return i; }//end if } return -1; } int main() { ifstream fin("camelot.in"); ofstream fout("camelot.out"); char column; //读入数据 fin >> R >> C; //读入国王 fin >> column >> king.r; king.c = column - 'A' + 1; grid[king.r][king.c] = KING; //读入骑士 while (!fin.eof()) { fin >> column >> knight[kl].r; if (knight[kl].r != 0) { knight[kl].c = column - 'A' + 1; if (grid[knight[kl].r][knight[kl].c] == KING) { //国王其实在同一个位置 grid[knight[kl].r][knight[kl].c] = KNIGHT; flag = true; } else { grid[knight[kl].r][knight[kl].c] = KNIGHT; } kl ++; } }//end while if (kl == 0) { fout << 0 << endl; return 0; } if(!flag) { //广度遍历国王到最短的骑士,按照骑士走法 path[0] = king; pl ++; int klnumber = 0; grid[king.r][king.c] = 0; for (int i=0; i < pl; i ++) { int r = path[i].r; int c = path[i].c; //左斜上 if (r > 1 && c > 2 ) { if (grid[r-1][c-2] == 0) { path[pl].r = r -1; path[pl].c = c -2; grid[r-1][c-2] = grid[r][c] + 1; pl ++; }//end if else if(grid[r-1][c-2] == KNIGHT) { path[pl].r = r -1; path[pl].c = c -2; pl ++; int index = getKnight(r-1,c-2); kingtoknight[index] = grid[r][c] + 1; grid[r-1][c-2] = grid[r][c] + 1; klnumber ++; }//end else if (klnumber == kl) { break; } } //左上 if (r > 2 && c > 1) { if (grid[r-2][c-1] == 0) { path[pl].r = r -2; path[pl].c = c -1; grid[r-2][c-1] = grid[r][c] + 1; pl ++; }//end if else if(grid[r-2][c-1] == KNIGHT) { path[pl].r = r -2; path[pl].c = c -1; pl ++; int index = getKnight(r-2,c-1); kingtoknight[index] = grid[r][c] + 1; grid[r-2][c-1] = grid[r][c] + 1; klnumber ++; }//end else if (klnumber == kl) { break; } } //右上 if (r > 2 && c + 1 <= C) { if (grid[r-2][c+1] == 0) { path[pl].r = r - 2; path[pl].c = c+ 1; grid[r-2][c+1] = grid[r][c] + 1; pl ++; }//end if else if(grid[r-2][c+1] == KNIGHT) { path[pl].r = r - 2; path[pl].c = c+ 1; pl ++; int index = getKnight(r-2,c+1); kingtoknight[index] = grid[r][c] + 1; grid[r-2][c+1] = grid[r][c] + 1; klnumber ++; }//end else if (klnumber == kl) { break; } } //右斜上 if (r > 1 && c + 2 <= C) { if (grid[r-1][c+2] == 0) { path[pl].r = r - 1; path[pl].c = c+ 2; grid[r-1][c+2] = grid[r][c] + 1; pl ++; }//end if else if (grid[r-1][c+2] ==KNIGHT) { path[pl].r = r - 1; path[pl].c = c+ 2; pl ++; int index = getKnight(r-1,c+2); kingtoknight[index] = grid[r][c] + 1; grid[r-1][c+2] = grid[r][c] + 1; klnumber ++; }//end else if (klnumber == kl) { break; } } //右斜下 if (r + 1 <= R && c + 2 <= C) { if (grid[r+1][c+2] == 0) { path[pl].r = r +1; path[pl].c = c+ 2; grid[r+1][c+2] = grid[r][c] + 1; pl ++; }//end if else if(grid[r+1][c+2]==KNIGHT) { path[pl].r = r +1; path[pl].c = c+ 2; pl ++; int index = getKnight(r+1,c+2); kingtoknight[index] = grid[r][c] + 1; grid[r+1][c+2] = grid[r][c] + 1; klnumber ++; }//end else if (klnumber == kl) { break; } } //右下 if (r + 2 <= R && c + 1 <= C) { if (grid[r+2][c+1] == 0) { path[pl].r = r +2; path[pl].c = c+ 1; grid[r+2][c+1] = grid[r][c] + 1; pl ++; }//end if else if(grid[r+2][c+1] == KNIGHT) { path[pl].r = r +2; path[pl].c = c+ 1; pl ++; int index = getKnight(r+2,c+1); kingtoknight[index] = grid[r][c] + 1; grid[r+2][c+1] = grid[r][c] + 1; klnumber ++; }//end else if (klnumber == kl) { break; } } //左下 if (r + 2 <= R && c - 1 >0) { if (grid[r+2][c-1] == 0) { path[pl].r = r +2; path[pl].c = c- 1; grid[r+2][c-1] = grid[r][c] + 1; pl ++; }//end if else if (grid[r+2][c-1] ==KNIGHT) { path[pl].r = r +2; path[pl].c = c- 1; pl ++; int index = getKnight(r+2,c-1); kingtoknight[index] = grid[r][c] + 1; grid[r+2][c-1] = grid[r][c] + 1; klnumber ++; }//end else if (klnumber == kl) { break; } } //左斜下 if (r + 1 <= R && c - 2 >0) { if (grid[r+1][c-2] == 0) { path[pl].r = r +1; path[pl].c = c- 2; grid[r+1][c-2] = grid[r][c] + 1; pl ++; }//end if else if (grid[r+1][c-2] == KNIGHT) { path[pl].r = r +1; path[pl].c = c- 2; pl ++; int index = getKnight(r+1,c-2); kingtoknight[index] = grid[r][c] + 1; grid[r+1][c-2] = grid[r][c] + 1; klnumber ++; }//end else if (klnumber == kl) { break; } } }//end for //国王到骑士的路径 for (int i=0; i < kl; i ++ ) { int absr = abs(knight[i].r - king.r); int absc = abs(knight[i].c - king.c); int temp = max(absr,absc); if (temp < kntok) { kntok = temp; knightk.r = knight[i].r; knightk.c = knight[i].c; }//end if }//end for }//end if !flag //遍历整个棋盘 for(int i=1; i <= R; i ++) { for (int j=1; j <= C; j ++) { initGrid(); path[0].r = i; path[0].c = j; pl = 1; int number = 0; if (grid[i][j] == KNIGHT) { number ++; } if (flag == true || (king.r == i && king.c == j)) { number ++; } grid[i][j] = 1; //广度遍历到所有骑士 for (int k=0; k < pl; k ++ ) { int r = path[k].r; int c = path[k].c; //左斜上 if (r > 1 && c > 2 ) { if (grid[r-1][c-2] == 0) { path[pl].r = r -1; path[pl].c = c -2; grid[r-1][c-2] = grid[r][c] + 1; pl ++; }//end if else if(grid[r-1][c-2] == KNIGHT||grid[r-1][c-2] == KING) { path[pl].r = r -1; path[pl].c = c -2; grid[r-1][c-2] = grid[r][c] + 1; number ++; pl ++; }//end else if (number == kl + 1) { break; } } //左上 if (r > 2 && c > 1) { if (grid[r-2][c-1] == 0) { path[pl].r = r -2; path[pl].c = c -1; grid[r-2][c-1] = grid[r][c] + 1; pl ++; }//end if else if(grid[r-2][c-1] == KNIGHT||grid[r-2][c-1] == KING) { path[pl].r = r -2; path[pl].c = c -1; grid[r-2][c-1] = grid[r][c] + 1; number ++; pl ++; }//end else if (number == kl + 1) { break; } } //右上 if (r > 2 && c + 1 <= C) { if (grid[r-2][c+1] == 0) { path[pl].r = r - 2; path[pl].c = c+ 1; grid[r-2][c+1] = grid[r][c] + 1; pl ++; }//end if else if(grid[r-2][c+1] == KNIGHT||grid[r-2][c+1] == KING) { path[pl].r = r - 2; path[pl].c = c+ 1; grid[r-2][c+1] = grid[r][c] + 1; number ++; pl ++; }//end else if (number == kl + 1) { break; } } //右斜上 if (r > 1 && c + 2 <= C) { if (grid[r-1][c+2] == 0) { path[pl].r = r - 1; path[pl].c = c+ 2; grid[r-1][c+2] = grid[r][c] + 1; pl ++; }//end if else if(grid[r-1][c+2] == KNIGHT||grid[r-1][c+2] == KING) { path[pl].r = r - 1; path[pl].c = c+ 2; grid[r-1][c+2] = grid[r][c] + 1; number ++; pl ++; }//end else if (number == kl + 1) { break; } } //右斜下 if (r + 1 <= R && c + 2 <= C) { if (grid[r+1][c+2] == 0) { path[pl].r = r +1; path[pl].c = c+ 2; grid[r+1][c+2] = grid[r][c] + 1; pl ++; }//end if else if(grid[r+1][c+2] == KNIGHT||grid[r+1][c+2] == KING) { path[pl].r = r +1; path[pl].c = c+ 2; grid[r+1][c+2] = grid[r][c] + 1; number ++; pl ++; }//end else if (number == kl + 1) { break; } } //右下 if (r + 2 <= R && c + 1 <= C) { if (grid[r+2][c+1] == 0) { path[pl].r = r +2; path[pl].c = c+ 1; grid[r+2][c+1] = grid[r][c] + 1; pl ++; }//end if else if(grid[r+2][c+1] == KNIGHT||grid[r+2][c+1] == KING) { path[pl].r = r +2; path[pl].c = c+ 1; grid[r+2][c+1] = grid[r][c] + 1; number ++; pl ++; }//end else if (number == kl + 1) { break; } } //左下 if (r + 2 <= R && c - 1 >0) { if (grid[r+2][c-1] == 0) { path[pl].r = r +2; path[pl].c = c- 1; grid[r+2][c-1] = grid[r][c] + 1; pl ++; }//end if else if(grid[r+2][c-1] == KNIGHT||grid[r+2][c-1] == KING) { path[pl].r = r +2; path[pl].c = c- 1; grid[r+2][c-1] = grid[r][c] + 1; number ++; pl ++; }//end else if (number == kl + 1) { break; } } //左斜下 if (r + 1 <= R && c - 2 >0) { if (grid[r+1][c-2] == 0) { path[pl].r = r +1; path[pl].c = c-2; grid[r+1][c-2] = grid[r][c] + 1; pl ++; }//end if else if(grid[r+1][c-2] == KNIGHT||grid[r+1][c-2] == KING) { path[pl].r = r +1; path[pl].c = c-2; grid[r+1][c-2] = grid[r][c] + 1; number ++; pl ++; }//end else if (number == kl + 1) { break; } } }//end for bool tempflag = false; int tempresult =0 ; //判断国王是否在骑士到集结地的路上 for (int m=0; m< kl; m++ ) { int tempking = grid[king.r][king.c]; if(!flag) { if (tempking + kingtoknight[m] == grid[knight[m].r][knight[m].c]) { tempflag = true; } }else tempflag = true; tempresult += grid[knight[m].r][knight[m].c] -1; }//end for if (tempflag || flag) { if (tempresult < result) { result = tempresult; } } else { //骑士接国王到集结地 int minload = LARGE; int minindex = -1; for (int n=0; n<kl; n ++) { if (minload > kingtoknight[n]) { minload = kingtoknight[n]; minindex = n; }//end if }//end for int tempresult2 = tempresult + minload - grid[knight[i].r][knight[i].c] + grid[king.r][king.c]; if (tempresult2 < result) { result = tempresult2; } //国王到最近的骑士,到集结地 int tempresult3 = tempresult + kntok; if (tempresult3 < result) { result = tempresult3; } //国王走到集结地 int absr = abs( king.r - i ); int absc = abs( king.c - j ); int tempresult4 = max(absr,absc) + tempresult; if (tempresult4 < result) { result = tempresult4; } } }//end j }//end i fout << result << endl; return 0; }

      运行结果如下:

Executing... Test 1: TEST OK [0.011 secs, 3040 KB] Test 2: TEST OK [0.011 secs, 3040 KB] Test 3: TEST OK [0.011 secs, 3040 KB] Test 4: TEST OK [0.000 secs, 3040 KB] Test 5: TEST OK [0.065 secs, 3040 KB] Test 6: TEST OK [0.097 secs, 3040 KB] Test 7: TEST OK [0.000 secs, 3040 KB] Test 8: TEST OK [0.011 secs, 3040 KB] Test 9: TEST OK [0.022 secs, 3040 KB] Test 10: TEST OK [0.086 secs, 3040 KB] Test 11: TEST OK [0.000 secs, 3040 KB] Test 12: TEST OK [0.000 secs, 3040 KB] Test 13: TEST OK [0.000 secs, 3040 KB] Test 14: TEST OK [0.011 secs, 3040 KB] Test 15: TEST OK [0.000 secs, 3040 KB] Test 16: TEST OK [0.000 secs, 3040 KB] Test 17: TEST OK [0.011 secs, 3040 KB] Test 18: TEST OK [0.022 secs, 3040 KB] Test 19: TEST OK [0.011 secs, 3040 KB] Test 20: TEST OK [0.000 secs, 3040 KB] All tests OK.

      

你可能感兴趣的:(USACO算法系列十六(续))