【NOIP2016提高A组8.11】钱仓

题目

这里写图片描述

分析

发现,一定有一个点作为起点,所有的路径都不经过这个起点。
接着贪心求答案,
如果(c_i>1),将其中(c_i-1)个钱往后“铺”。
易证(x^2+y^2<=(x+y)^2)
那么维护一个队列,先进先出,就能保证最小。

#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
const int maxlongint=2147483647;
const int mo=1000000007;
const int N=150005;
using namespace std;
int d[N],c[N*2],n,m,tot,mak[N];
long long ans;
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&c[i]);
		c[i+n]=c[i];
	}
	for(int i=1;i<=n;i++)
	{
		tot=ans=0;
		int sum=0,head=1;
		for(int j=1;j<=n;j++)
		{
			mak[j]=c[i+j-1];
			sum+=mak[j];
			if(sum<j) 
			{
				ans=-1;
				break;
			}
		}
		if(ans>=0)
		for(int j=1;j<=n;j++)
		{
			while(mak[j]--) 
			{
				d[++tot]=j;
			}
			mak[j]++;
			ans+=(j-d[head])*(j-d[head]);
			head++;
		}
		if(ans>=0) 
		{
			printf("%lld",ans);
			return 0;
		}
	}
}
原文地址:https://www.cnblogs.com/chen1352/p/9043452.html