1. 程式人生 > 實用技巧 >Civilization - 很妙的搜尋模擬

Civilization - 很妙的搜尋模擬

傳送門
題意是給出一個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;
}