摘樱桃
时间限制: 1 Sec 内存限制: 128 MB提交: 77 解决: 30
[ 提交][ 状态][ 讨论版]
题目描述
有n个樱桃排成一列,第i个樱桃的甜度为v[i],你要把n个樱桃分成若干组,其中每一组的樱桃必须相邻。每一组樱桃的美味度为(sum-T)^2,其中sum是这组樱桃的甜度之和,T为输入给定的系数。
一组方案的美味度为每一组的美味度之和。
求可行方案最小的美味度。
一组方案的美味度为每一组的美味度之和。
求可行方案最小的美味度。
输入
第一行两个正整数n,T。
第二行n个整数,第i个整数是第i个樱桃的甜度,v[i]。
第二行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