题目链接
题目链接(可提交)
题意:
经营模拟类游戏,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)
*/