• 均衡操作2


    小J面前有N桶水,每个桶装的水的体积不一样

    现在小J希望让所有桶的水的体积变得一样

    每次他会选择两个相邻的桶子, 将桶中的水都倒掉1个单位

    问他至少倒掉多少水,使得所有桶的水一样多,如果达不到目的,输出-1

    Format
    Input
    第一行给出数字T,代表数据的组数

    对于每组数据,先给出N 下面一行给出N个数字,代表每个桶的水的体积

    N<=1e5

    体积<=1e9

    Output
    如题

    Samples
    输入数据 1
    2
    3
    8 10 5
    6
    4 6 4 4 6 4
    输出数据 1
    14
    16
    Hint

    第1次,将第2个与第3个桶子都倒掉2个单位的水

    第2次,将第1个与第2个桶子都倒掉5个单位的水

    Sol:我们先来看样例的操作过程 

    既然要让所有数字变得一样,那当然要找到最大的那个数字10,让10与5一起减少2,这样10就变成了8

    与左边的8变成一样。于是变成

    8 8 3

    然后再将最左边两个数字8 8一起减少5,得到 3 3 3.

    此时我们会发现,如果每次在要数列中找最大值来减,是个比较麻烦的事。

    又发现,在整个操作中,只要最终达到目的,先减哪个,再减哪个,并不重要。。。。

    于是仍以样例来说

    8 10 5

    我们的目标是让所有数字变成一样

    于是对于10来说,它比左边的8大,于是10就要变小,而按题意,相邻的两个数字都要变

    于是10就拉上右边的5一起变,变成

    8 8 3

    通过这样的变化,我们能使整个数列的第1个数字到第N-1数字,它们会变成一个不上升的数列(当然最理想的状态是前N-1个数字变得一样了)

    接下来,我们可以将8 8 3倒过来得到3 8 8

    再按上面的思路做一遍得到3 3 3

    当然这个操作过程中还两个细节

    1:

    在做完第一遍操作后,整个数列必须是一个不上升的数列,否则是无解的。

    例如

    8 10 20

    这个数据就是无解的。

    2:在做第二遍的时候,必须保证最左边那个数字是不能为负数的

    例如数据

    6 10 3

    如果让10与3一起减少4的话,则3会变成-1.

    后面的操作就无法进行下去的。。。。。。。负数怎么减少啊!!!

    总结:

    1:这个题其实是一种步步逼近的方式

    2:如果发现操作的先后顺序与最终结果没有关系 ,就不妨统统从左向右做。。。类似于NOIP那个经典题均分纸牌。

    #include<bits/stdc++.h>
    #define int long long
    #define isdight(c) (c>='0'&&c<='9')
    #define swap(a,b) a^=b^=a^=b
    using namespace std;
    int t,n,h[100005];
    inline int read() //快读
    {
    	int x=0,f=1;
    	char c=getchar();
    	while(!isdight(c))
    		f=(c^'-'?1:-1),c=getchar();
    	while(isdight(c))
    		x=(x<<1)+(x<<3)+c-'0',c=getchar();
    	return x*f;
    }
    int solve()
    {
    	int ans=0;
    	if(n<2)
    		return 0; //无需改变
    	for(int j=1;j<=2;j++) //正序变化与倒序变化
    	{
    		for(int i=2;i<n;i++)
    		{
    			if(h[i]>h[i-1])
    			{
    				int differ=h[i]-h[i-1];
    				ans+=differ*2; //每次喂两袋
    				h[i+1]-=differ;
    				h[i]=h[i-1]; //同时变化
    			}
    		}
    		if(h[n]>h[n-1])
    			return -1; //无解
    		if(h[n]<0)
    			return -1; //无解
    		reverse(h+1,h+1+n); //反转
    	}
    	return ans;
    }
    signed main()
    {
    	t=read();
    	while(t--)
    	{
    		n=read();
    		for(int i=1;i<=n;i++)
    			h[i]=read();
    		printf("%lld\n",solve());
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    关于Python的super用法研究
    服务器提示缺少JAVA_HOME
    python_popen
    nslookup
    day2--深copy和浅copy
    if/while/fore根据编号购买商品
    标志位的用法
    python 循环和file操作实现用户密码输错三次将用户锁定
    day01项目:用户三次登陆锁定
    day01——python从认识开始
  • 原文地址:https://www.cnblogs.com/cutemush/p/16683777.html
Copyright © 2020-2023  润新知