http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?cid=889&pid=1004
这题在原点是建城市,是可以在时间0建,时间1就开始收粮食的,被题意坑了,过了以后才发广播。
先算出到达(x,y)并建好城市需要dis[x][y]的时间,然后把(x,y)距离以内的位置拿出来a[i][j]从大到小排个序,多一个人口肯定去较大的地方,然后枚举人口,计算一下要多少天多一个人口就行了,最后所有位置的答案取个min
#include
using namespace std;
typedef long long ll;
const int maxl=510;
int n,m,cas,k,cnt,tot,ans,sx,sy;
int up[maxl],b[maxl];
int a[maxl][maxl],dis[maxl][maxl],val[maxl][maxl];
struct node {int x,y;};
char s[maxl];
inline int dist(int i,int j,int x,int y)
{
return abs(i-x)+abs(j-y);
}
inline void prework()
{
scanf("%d%d%d",&n,&sx,&sy);
int d;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
scanf("%d",&a[i][j]);
d=dist(i,j,sx,sy);
dis[i][j]=d/2+(d&1);
}
}
inline bool cmp(const int &x,const int &y)
{
return x>y;
}
inline void mainwork()
{
for(int i=1;i<=8;i++)
up[i]=8*i*i;
ans=2e9;
int now,sum,d,res,ind;
for(int x=1;x<=n;x++)
for(int y=1;y<=n;y++)
{
cnt=0;val[x][y]=0;
for(int i=max(1,x-3);i<=min(n,x+3);i++)
for(int j=max(1,y-3);j<=min(n,y+3);j++)
if(dist(x,y,i,j)<=3 && !(x==i && y==j))
b[++cnt]=a[i][j];
sort(b+1,b+1+cnt,cmp);
sum=0;now=a[x][y];ind=1;
for(int i=1;i<=8;i++)
{
if(sum>=up[i])
{
if(ind<=cnt)
now+=b[ind],++ind;
continue;
}
res=up[i]-sum;
d=res/now+(res%now!=0);
val[x][y]+=d;
sum+=d*now;
if(ind<=cnt)
now+=b[ind],++ind;
}
ans=min(ans,dis[x][y]+val[x][y]);
}
}
inline void print()
{
printf("%d\n",ans);
}
int main()
{
int t=1;
scanf("%d",&t);
for(cas=1;cas<=t;cas++)
{
prework();
mainwork();
print();
}
return 0;
}