因为在允许的情况下,必然是左右手交替进行,这样不会增加多余的无谓的能量。
然后根据不同的分界点,肯定会产生左手或右手重复使用的情况,这是就要加上Qr/Ql * 次数。
一开始的想法,很直接,枚举每个分界点,计算出总共要用的能量,取最小的那个即是答案:
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 int main() 5 { 6 int n,l,r,Q_l,Q_r,w[100000+5]; 7 scanf("%d%d%d%d%d",&n,&l,&r,&Q_l,&Q_r); 8 for(int i=1;i<=n;i++) scanf("%d",&w[i]); 9 10 int ans=2147483647,left_enegry_sum,right_enegry_sum; 11 for(int m=0;m<=n;m++) //边界在m右边 12 { 13 left_enegry_sum=0,right_enegry_sum=0; 14 for(int i=1;i<=m;i++) left_enegry_sum+=w[i]*l; 15 for(int i=n;i>m;i--) right_enegry_sum+=w[i]*r; 16 if(m < n-m) //右手拿的东西多 17 right_enegry_sum += ( (n-m) - m - 1 ) * Q_r; 18 else if(m > n-m) //左手拿的东西多 19 left_enegry_sum += ( m - (n-m) - 1 ) * Q_l; 20 ans=min(ans , left_enegry_sum + right_enegry_sum); 21 //printf("now: left_enegry_sum=%d right_enegry_sum=%d enegry_sum=%d ",left_enegry_sum,right_enegry_sum,ans); 22 } 23 printf("%d ",ans); 24 }
但是在数据来那个很大的情况下会超时。
所以考虑到我们的枚举分界点方向是从左到右,那么我们不需要每次枚举分界点都O(n)地去计算左右手拿物品的能量
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 int main() 5 { 6 int n,l,r,Q_l,Q_r,w[100000+5]; 7 scanf("%d%d%d%d%d",&n,&l,&r,&Q_l,&Q_r); 8 for(int i=1;i<=n;i++) scanf("%d",&w[i]); w[0]=0; 9 10 int ans=2147483647,left_energy_sum=0,right_energy_sum=0; 11 for(int i=1;i<=n;i++) right_energy_sum+=w[i]*r; 12 for(int m=0;m<=n;m++) //边界在m右边 13 { 14 left_energy_sum+=w[m]*l; //分界点右移一位,left_enrgy_sum增加新增的那一个物品消耗的能量即可 15 right_energy_sum-=w[m]*r; //分界点右移一位,right_enrgy_sum减少那一个物品消耗的能量即可 16 if(m < n-m) //右手拿的东西多 17 ans=min(ans , left_energy_sum + right_energy_sum + ( (n-m) - m - 1 ) * Q_r); 18 else if(m > n-m) //左手拿的东西多 19 ans=min(ans , left_energy_sum + ( m - (n-m) - 1 ) * Q_l + right_energy_sum); 20 else //两只手拿的一样多 21 ans=min(ans , left_energy_sum + right_energy_sum); 22 //printf("now: left_energy_sum=%d right_energy_sum=%d energy_sum=%d ",left_energy_sum,right_energy_sum,ans); 23 } 24 printf("%d ",ans); 25 }