Civilization - 很妙的搜尋模擬
阿新 • • 發佈:2020-07-20
傳送門
題意是給出一個n*n的矩陣,表示每回合如果有居民就生產的糧食數,以及一個起點x,y,然後主人公可以沒回合進行選擇,是移動還是建造城市,如果建造城市,那麼主人公就不能再移動,也就是說,只能建造一個城市,然後在這個城市進行生產糧食,最後得到人口,再派遣到周圍去生產糧食。求得到人口為9時的最小回合數
之前題意沒懂,然後第二遍看題時,以模擬的思維進行,每回合進行一次操作,要麼進行建造,要麼移動。
但其實建造只有一次,那麼我們可以求出在所有點進行建造時的最小回合數,然後再求出這個點到起點的距離,求出要走多少回合。
對於每個點進行建造,首先該點必須考慮,然後在周圍的點裡找出最大的8個點,按照降序進行生產糧食。模擬即可
#include <iostream> #include <cstdio> #include <vector> #include <algorithm> #include <cmath> using namespace std; const int N = 505; int a[N][N]; void solve(){ int n, x, y, ans = 0x3f3f3f3f; cin >> n >> x >> y; for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) scanf("%d", &a[i][j]); for(int i = 1; i <= n; i++){ for(int j = 1; j <= n; j++){ std::vector<int> v; v.push_back(a[i][j]); for(int k = i - 3; k <= i + 3; k++) { for(int z = j - 3; z <= j + 3; z++) { if(k < 1 || k > n || z < 1 || z > n) continue; if(abs(k - i) + abs(z - j) > 3) continue; if(k == i && j == z) continue; v.push_back(a[k][z]); } } sort(v.begin() + 1, v.end()); reverse(v.begin() + 1, v.end()); v.resize(9); int each = v[0], tot = 0, times = 0; for(int k = 1; k <= 8; k++) { int need = 8 * k * k; if(tot < need) { int waittimes = (need - tot + each - 1) / each; times += waittimes; tot += each * waittimes; } each += v[k]; } int dis = abs(i - x) + abs(j - y); times += (dis + 1) / 2; // 需要一回合建造城市 ans = min(ans, times); } } printf("%d\n", ans); } int main(){ int t; cin >> t; while(t--) solve(); return 0; }