Bestcoder-889-1004-Civilization(HDU6746)

题目链接

题目链接(可提交)

题意:

经营模拟类游戏,n*n地图(5e2*5e2),每个地点有一定生产力a[i][j],初始位置在(x,y)建城市,初始居民1人

第一阶段:移动城市,每天可以将城市移动到曼哈顿距离不超过2的地方。

第二阶段:生产,在确保城市有人的前提下,多余的市民可以去离城市曼哈顿距离不超过3的地方生产

第二阶段每天结算一次

首先结算粮食,所有有居民的地点均可获得粮食a[i][j],粮食汇总到城市

再结算人口,若当前城市总粮食数达到8倍人口数平方(food>=8*p*p),则当前城市人口增长1人

最后结算游戏,当城市人口达到9人时,结束游戏

求通关该游戏所需的最少天数

思路:

这题最大的困难就是读题,理解复杂晦涩的游戏规则是一切的前提。对于城市,人口,生产这一堆概念的理解确实不是很容易。

注意城市可以连续移动,人口却不可连续移动

一旦读懂了题意,一切就都简单了。

对于第二阶段,肯定在确保城市有人的情况下,每天都尽量把人口安排去生产力大的地方,然后模拟游戏所需天数

而至于第一阶段,究竟改把城市建在什么地方,直接暴力枚举即可

最后,一个小细节,就是第二阶段只可以按人口模拟,模拟每次人口增长所需要的天数,而不能按照天数一天天模拟,否则会超时

代码:

/*
Author Owen_Q
*/

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int maxn = 5e2+5;

int a[maxn][maxn];

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,x,y;
        //freopen(".txt","r",stdin);
        //ios::sync_with_stdio(false);
        //cin.tie(0);
        scanf("%d%d%d",&n,&x,&y);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                scanf("%d",&a[i][j]);
        int re = 1e9;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                int dis = abs(x-i) + abs(y-j);
                int now = (dis-1)/2+1;
                if(x==i&&y==j)
                    now = 0;
                vector<int> reg;
                for(int ii=i-3;ii<=i+3;ii++)
                {
                    for(int jj=j-3;jj<=j+3;jj++)
                    {
                        if(ii<=0||ii>n||jj<=0||jj>n)
                            continue;
                        if(ii==i&&jj==j)
                            continue;
                        if(abs(ii-i) + abs(jj-j) > 3)
                            continue;
                        reg.push_back(a[ii][jj]);
                    }
                }
                int regn = reg.size();
                while(regn<7)
                {
                    reg.push_back(0);
                    regn++;
                }
                sort(reg.begin(),reg.end(),greater<int>());
                int p = 1;
                int food = 0;
                int foodinc = a[i][j];
                int foodneed = 8;
                while(p<9)
                {
                    int day = (foodneed-1) / foodinc + 1;
                    now += day;
                    p++;
                    food += foodinc * day;
                    foodinc += reg[p-2];
                    foodneed = 8*p*p - food;
                }
                re = min(re,now);
            }
        }
        printf("%d\n",re);
    }
    return 0;
}

/*
计算每次人口增长所需时间
注意细节(曼哈顿距离小于等于3)
*/

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值