// 圈地為王遊戲樣例程式
// 最後更新 2013-06-25 21:56
#include #include #include #include #include #include #define initial_owner -1 // 無主
#define temporary_flag -2 // 臨時標誌
#define max(a, b) ((b < a) ? (a) : (b))
#define min(a, b) ((a < b) ? (a) : (b))
#define player_count 4
#define field_width 10
#define field_height 10
using namespace std;
struct point
point()
bool operator<(const point& b) const
bool operator==(const point& b) const
bool operator!=(const point& b) const
void operator+=(const point& b) };
int playerleft, myid, turncount, vborders[field_width + 1][field_height], hborders[field_width][field_height + 1], //記錄軌跡用
vborderowner[field_width + 1][field_height], hborderowner[field_width][field_height + 1], // 記錄可否行走用
grids[field_width][field_height], areasquaresum[player_count], areasum[player_count], // 記錄格仔占領情況
dx[5] = , dy[5] = , playerstate[player_count], // 0為抬筆,1為落筆,-1為死亡
stuckstatusleft[player_count], // 玩家被束縛剩餘回合數
scoredecline[player_count]; // 玩家因施放技能損失的分數
char actions[5] = ,
lastdir[player_count]; // 上次走的方向,僅用於落筆後狀態
point prevpos[player_count], currpos[player_count];
vectortrail[player_count];
settraps;
struct enclosingargu
};inline void drawline(int charid, point& prevpos, point& currpos)
inline bool movestep(int &x, int &y, int dir, int charid) // 移動並檢查是否撞到charid邊界
else if (dir == 1)
else if (dir == 2)
else if (dir == 3)
x += dx[dir];
y += dy[dir];
if (x < 0 || x >= field_width || y < 0 || y >= field_height)
return false;
return true;
}inline bool movestep(int &x, int &y, int dir) // 移動
int tryexpand(int charid, int tempboard[field_width][field_height], int gridx, int gridy,
set& actuallyoccupiedarea, bool willbedead[player_count]) // 試圖用漫水法找出charid所圍全部區域
if (gridx > 0 && gridx < field_width && gridy > 0 && gridy < field_height &&
hborders[gridx - 1][gridy] != charid && hborders[gridx][gridy] != charid &&
vborders[gridx][gridy - 1] != charid && vborders[gridx][gridy] != charid)
if (initialowner == initial_owner)
actuallyoccupiedarea.insert(point(gridx, gridy));
return area + 1;
}int tryexpand(int tempboard[field_width][field_height], int gridx, int gridy, set& allarea) // 試圖用漫水法從gridx/y開始找出內容為tempflag的連續格仔面積
return area + 1;
}// 產生圈地的引數,因為根據規則,在正式圈地之前還要從小到大排序
enclosingargu calcenclose(int charid, vector::iterator p, vector::iterator e) // p~e是真正在邊界上的點
// 按照圈地引數進行正式圈地
void doenclose(const enclosingargu& argu)
// 標記所有內部邊
point x1, x2;
for (x1.x = 0; x1.x < field_width; x1.x++)
for (x1.y = 0; x1.y < field_height; x1.y++)
if (x1.y < field_height - 1)
};areasum[argu.charid] += argu.actuallyoccupiedarea.size();
setallarea;
// 找出所有連續的區域
for (i = argu.actuallyoccupiedarea.begin(); i != e; i++)
if (tempgrids[i->x][i->y] == temporary_flag)
;// 清除軌跡
int x, y;
for (x = 0; x <= field_width; x++)
for (y = 0; y <= field_height; y++)
;trail[argu.charid].clear();
}bool checkroute(int charid, int state, point& prevpos, point& currpos) // 檢查路線是否可以行走
else
if (currpos.x == 0 || currpos.x == field_width)
return true;
else }
inline bool checkposvalidity(point& pos)
inline bool isreverse(int dir1, int dir2) // 判斷方向是否相反
inline int getdistance(int ida, int idb) // 獲得兩名角色之間的座標差
int main()
if (y != field_height)
if (x != field_width && y != field_height)
grids[x][y] = initial_owner;
};for (i = 0; i < player_count; i++)
turncount = 0;
while (cin >> cmd)
if (cmd == "[status]")
if (++turncount == 1) // 第一回合
for (i = 0; i < player_count; i++)
prevpos[i] = currpos[i];
else
else if (playerstate[i] == 1)}}
for_each(allenclosure.begin(), allenclosure.end(), doenclose);
allenclosure.clear();
}if (stuckstatusleft[myid] > 0)
if (playerstate[myid] == 0)
else if (rand() % 2)
else
changepenstate = 0;
}else
changepenstate = 0;
if (playerstate[myid] == 1) // 落筆態
if (i != 4)
lastdir[myid] = i;
}else // 抬筆態
while (true)
;cout << "[action] " << actions[i] << ' ' << changepenstate << endl;
for (i = 0; i < player_count; i++)
prevpos[i] = currpos[i];
}}}
GMOJ4016 圈地為王
在 n 行 m 列的網格中,你要圈一些地。你從左上角出發,最後返回左上角,路徑內部的區域視為被你圈住。你不可以進入網格內部,只能在邊上行走。你的路徑不能在左上角以外自交,但是邊足夠寬,你可以重複經過而不自交。網格中有一些格仔對你很重要,你要盡量圈住它 而另一些格仔對你有壞處,你不能圈住它。求圈住 i...
JZOJ 4016 圈地為王
description 在 n 行 m 列的網格中,你要圈一些地。你從左上角出發,最後返回左上角,路徑內部的區域視為被你圈住。你不可以進入網格內部,只能在邊上行走。你的路徑不能在左上角以外自交,但是邊足夠寬,你可以重複經過而不自交。網格中有一些格仔對你很重要,你要盡量圈住它 而另一些格仔對你有壞處,...
搜尋,計算幾何 JZOJ 4016 圈地為王
在 n 行 m 列的網格中,你要圈一些地。你從左上角出發,最後返回左上角,路徑內部的區域視為被你圈住。你不可以進入網格內部,只能在邊上行走。你的路徑不能在左上角以外自交,但是邊足夠寬,你可以重複經過而不自交。網格中有一些格仔對你很重要,你要盡量圈住它 而另一些格仔對你有壞處,你不能圈住它。求圈住 i...