• 均衡操作


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

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

    每次他会选择两个相邻的桶子,将一个桶的水倒入另一个桶,然后将空桶丢掉。

    问他至少操作多少次,使得所有桶的水一样多。

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

    对于每组数据,先给出N

    下面一行给出N个数字,代表每个桶的水的体积

    N<=1e5

    T<=10

    所有数字之和<=1e6

    Output
    如题

    Samples
    输入数据 1
    1
    6
    1 2 3 1 1 1
    输出数据 1
    3
    Hint

    第1次,小J将第1个与第2个桶合并,得到数列(3,3,1,1,1)

    第2次,小J将第4个与第5个桶合并,得到数列(3,3,1,2)

    第2次,小J将第3个与第4个桶合并,得到数列(3,3,3)

    Sol:

    每个水桶开始的体积知道了,于是总体积sum也就知道了。

    发现每次合并就减少一个桶,于是如果知道最终还有多少个桶,就知道了合并了几次

    于是我们逆序枚举一下,最终还有多少个桶,设之为i

    于是每个桶最终的体积为sum/i,自然sum%i必须为0

    接下来,我们就来检查一下,合并的过程中是否有出错

    由于在合并时,是不断将小数字合并成一个大数字,于是如果发现合并后的体积,或者某个水桶目前的体积是大于sum/i的,则合并是出错的。

    例如

    4个桶

    1 2 3 6

    于是sum=1+2+3+6=12

    假设i=3,于是sum/i=12/3=4

    于是我们从左扫到右

    就会发现1+2+3=6>4

    于是合并失败

    再让i=2,sum/i=12/2=6

    发现合并的过程是不会出错的。

    于是合并的次数就等于 N-i=4-2=2

    总结:

    这个题还是比较简单的,有多种枚举方式,例如枚举最终每个桶的水的体积是多少。

    当然这个体积也必须是总体积sum的约数才行。

    方法1:枚举最终留下多少个桶

    #include<bits/stdc++.h>
    using namespace std;
    int a[1000006];
    int main() {
      int T;
      cin >> T;
      while (T--) 
      {
        int n;
        cin >> n;
        int sum = 0;
        for (int i = 0; i < n; i++) 
    	{
          cin >> a[i];
          sum += a[i];
        }
        int ans;
        for (int i = n; i >= 1; i--) 
        //最后剩下多少堆 
    	{ 
              if (sum % i != 0)
                  continue;
              int cur = 0;
              bool flag = 1;
              for (int j = 0; j < n; j++) 
    	      {
                       cur += a[j];
                       if (cur > sum / i) 
    		           {
                            flag = 0;
                            break;
                       } 
    		          else if (cur == sum / i) 
    		          {
                              cur = 0;
                      }
             }
          if (flag) 
    	  {
            ans = n - i;
            break;
          }
        }
        cout << ans << endl;
      }
      return 0;
    }
    

      

     方法2:枚举体积

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+5;
    int t,n,s,cnt,a[maxn],p[1005],res,ans;
    bool flag;
    int main()
    {
    	scanf("%d",&t);
    	while(t--)
    	{
    		flag=ans=cnt=s=0;
    		scanf("%d",&n);
    		for(int i=1;i<=n;i++)
    		{
    			scanf("%d",&a[i]);
    			flag|=(a[i]!=a[1]);
    			s+=a[i];
    		}
    		if(!flag)
    		{
    			printf("0\n");	continue;
    		}
    		for(int i=1;i<=s;i++)
    		{
    			if(s%i)
    				continue;
    			p[++cnt]=i;
    		}
    		for(int i=1;i<=cnt;i++)
    		//枚举每个桶里有多少水,从小到大枚举,找到第一个解就退出 
    		{
    			res=ans=0;
    			bool ok=true;
    			for(int j=1;j<=n;j++)
    			{
    				res+=a[j];
    				ans++;
    				if(res==p[i])
    				{
    					res=0;
    					ans--;
    				}
    				if(res>p[i])
    				{
    				     ok=false;
    					 break;	
    			    }
    			
    	    	}
    	      	if (ok==true)
    	    	{
    	    	
        		     printf("%d\n",ans);
        		     break;
    	        }
    	    }
        }
    	return 0;
    }
    

      

  • 相关阅读:
    BZOJ3171: [Tjoi2013]循环格
    Luogu P1850 换教室(期望dp)
    Luogu P3825 [NOI2017]游戏(2-SAT)
    Luogu P3007 [USACO11JAN]大陆议会The Continental Cowngress
    Luogu P2272 [ZJOI2007]最大半连通子图(Tarjan+dp)
    Luogu P3209 [HNOI2010]平面图判定(2-SAT)
    Luogu P4171 [JSOI2010]满汉全席(2-SAT)
    Luogu P4782 【模板】2-SAT 问题(2-SAT)
    Luogu P2845 [USACO15DEC]Switching on the Lights 开关灯(bfs)
    Luogu P4933 大师(dp)
  • 原文地址:https://www.cnblogs.com/cutemush/p/16676755.html
Copyright © 2020-2023  润新知