题意:给定正整数序列 a,将a[i]拆分为xi+yi,并且xi和yi满足对于给定s (xi−s)⋅(yi−s)≥0,
求:F=a1⋅x2+y2⋅x3+y3⋅x4+…+yn−2⋅xn−1+yn−1⋅an.的最小值。
思路:要让结果最小,就要把最大的分配给a0去乘,最小的分配给a2去乘。那么如果没有s的限制,结果就是a0∗ a1 + a2∗0。现在有s的限制,我们也只需把a1拆分成尽量一个最大一个最小就行了。我们假定dp[i][0]表示a[i]将拆出来的x与前项相乘所得的到目前为止的最小值,相对的,dp[i][1]就表示将拆出来的y与前项相乘所得的到目前为止的最小值,最后的答案就是将a[n]分别与dp[n-1][0]和dp[n-1][1]所代表的状态计算并比较得出最小值。
AC代码:
#include<bits/stdc++.h>
#define lmw ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define int long long
using namespace std;
const int N=1e6+10;
int dp[N][2];
int a[N][2];
signed main(){
lmw;
int t;
cin>>t;
while(t--){
int n,s;
cin>>n>>s;
int op=0;
for(int i=1;i<=n;i++){
cin>>a[i][1];
op=a[n][1];
if(a[i][1]>=s){
a[i][1]=a[i][1]-s;
a[i][2]=s;
}
else {
a[i][2]=a[i][1];
a[i][1]=0;
}
}
for(int i=2;i<n;i++){
if(i==2){
dp[i][1]=(a[1][1]+a[1][2])*a[i][1];
dp[i][2]=(a[1][1]+a[1][2])*a[i][2];
}
else {
dp[i][1]=min(dp[i-1][1]+a[i-1][2]*a[i][1],dp[i-1][2]+a[i-1][1]*a[i][1]);
dp[i][2]=min(dp[i-1][1]+a[i-1][2]*a[i][2],dp[i-1][2]+a[i-1][1]*a[i][2]);
}
}
cout<<min(dp[n-1][1]+a[n-1][2]*op,dp[n-1][2]+a[n-1][1]*op)<<"\n";
}
}