2018山东冬令营:摘樱桃 (思维)
摘樱桃
时间限制: 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
岂曰无衣?与子同袍。王于兴师,修我戈矛。与子同仇!
岂曰无衣?与子同泽。王于兴师,修我矛戟。与子偕作!
岂曰无衣?与子同裳。王于兴师,修我甲兵。与子偕行!