2018山东冬令营:摘樱桃 (思维)

摘樱桃

时间限制: 1 Sec  内存限制: 128 MB
提交: 77  解决: 30
[提交][状态][讨论版]

题目描述

有n个樱桃排成一列,第i个樱桃的甜度为v[i],你要把n个樱桃分成若干组,其中每一组的樱桃必须相邻。每一组樱桃的美味度为(sum-T)^2,其中sum是这组樱桃的甜度之和,T为输入给定的系数。
一组方案的美味度为每一组的美味度之和。
求可行方案最小的美味度。

输入

第一行两个正整数n,T。
第二行n个整数,第i个整数是第i个樱桃的甜度,v[i]。

输出

一行一个非负整数,为最小美味度。

样例输入

5 5

3 5 2 1 6

样例输出

9

提示

对于50%的数据满足 n<=10,T<=1000,v[i]<=10
对于70%的数据满足 n<=100
对于所有数据,n<=10^3,T<=1000,v[i]<=10


【】

问题难点在于 如何考虑分组的情况,  分组有很多种。

【转换】

    可以这样想,认为每一组 是 一个点,  然后  建立一个 超级原点  每个点 与原点 建立关系,  权值就是如题所述,

   汇点就是 n  这样 就变成 从 原点到 n点的最短距离 SPFA  就可以解决;

分组时 需要 记录前缀和, 利用前缀和只差来计算 分组。

具体看代码:

【代码实现】

//#include <bits/stdc++.h>
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cmath>
#include <math.h>
#include <cstring>
#include <string>
#include <queue>
#include <deque>
#include <stack>
#include <stdlib.h>
#include <list>
#include <map>
#include <utility>
#include <set>
#include <bitset>
#include <vector>
#define mem(a,b) memset(a,b,sizeof(a))
#define findx(x,b,n) lower_bound(b+1,b+1+n,x)-b
#define FIN      freopen("input.txt","r",stdin)
#define FOUT     freopen("output.txt","w",stdout)
#define SHUT ios_base::sync_with_stdio(false); cout.setf(ios::fixed); cout.precision(20); cout.tie(nullptr); cin.tie(nullptr);
#define lson rt << 1, l, mid
#define rson rt << 1|1, mid + 1, r
#define  FI(n) IO::read(n)
#define  Be IO::begin()

using namespace std;
typedef long long ll;
const double PI=acos(-1);
const ll INF=0x3f3f3f3f;
const double esp=1e-6;
const int maxn=1e6+5;
const int MAXN=1e6+5;
const int MOD=1e9+7;
const int mod=1e9+7;
int dir[5][2]={0,1,0,-1,1,0,-1,0};

/*
namespace IO {
	const int MT = 5e7;
	char buf[MT]; int c,sz;
	void begin(){
		c = 0;
		sz = fread(buf, 1, MT, stdin);//一次性输入
	}
	template<class T>
	inline bool read(T &t){
		while( c < sz && buf[c] != '-' && ( buf[c]<'0' || buf[c] >'9')) c++;
		if( c>=sz) return false;
		bool flag = 0; if( buf[c]== '-') flag = 1,c++;
		for( t=0; c<=sz && '0' <=buf[c] && buf[c] <= '9'; c++ ) t= t*10 + buf[c]-'0';
		if(flag) t=-t;
		return true;
	}
}
*/
inline void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){ x=1; y=0; d=a; }else{ ex_gcd(b,a%b,d,y,x); y-=x*(a/b);};}
inline ll gcd(ll a,ll b){ return b?gcd(b,a%b):a;}
inline ll exgcd(ll a,ll b,ll &x,ll &y){if(!b){x=1;y=0;return a;}ll ans=exgcd(b,a%b,x,y);ll temp=x;x=y;y=temp-a/b*y;return ans;}
inline ll lcm(ll a,ll b){ return b/gcd(a,b)*a;}
inline ll qpow(ll x,ll n){ll res=1;for(;n;n>>=1){if(n&1)res=(res*x)%MOD;x=(x*x)%MOD;}return res;}
inline ll inv_exgcd(ll a,ll n){ll d,x,y;ex_gcd(a,n,d,x,y);return d==1?(x+n)%n:-1;}
inline ll inv1(ll b){return b==1?1:(MOD-MOD/b)*inv1(MOD%b)%MOD;}
inline ll inv2(ll b){return qpow(b,MOD-2);}



int head[MAXN];
ll dis[MAXN],vis[MAXN];
int cot;
struct node{
    ll v,w,next;
}edge[MAXN];

void init()
{
    cot=0;
    memset(head,-1,sizeof(head));
}
void add(int u,int v,ll w)
{
    edge[++cot].v=v;
    edge[cot].w=w;
    edge[cot].next=head[u];
    head[u]=cot;
}

void SPFA(int st)
{
    memset(vis,0,sizeof(vis));
    memset(dis,INF,sizeof(dis));
    queue<int> Q;
    vis[st]=0;
    dis[st]=0;
    Q.push(st);
    while(!Q.empty())
    {
        int u=Q.front();
        Q.pop();
        vis[u]=0;
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            ll v=edge[i].v;
            ll w=edge[i].w;
            if(dis[v]>dis[u]+w)
            {
                dis[v]=dis[u]+w;
                if(!vis[v])
                {
                    vis[v]=1;
                    Q.push(v);
                }
            }
        }
    }
}

ll sum[MAXN];
int main()
{
    SHUT;
    ll n,t;
    init();
    cin>>n>>t;
    ll x;
    mem(sum,0);
    for(int i=1;i<=n;i++)
    {
        cin>>x;
        sum[i]=sum[i-1]+x;
    }
    for(int i=0;i<=n;i++)
    {
        for(int j=i+1;j<=n;j++)
        {
            ll w=(sum[j]-sum[i]-t)*(sum[j]-sum[i]-t);
            add(i,j,w);
        }
    }
    SPFA(0);
    cout<<dis[n]<<endl;
    return 0;
}

123


posted @ 2018-03-11 20:19  Sizaif  阅读(165)  评论(0编辑  收藏  举报