zoukankan      html  css  js  c++  java
  • 【BZOJ1110】[POI2007] 砝码(进制分解)

    点此看题面

    大致题意:(n)个背包和(m)个砝码,每个背包有一定的重量限制,而砝码两两之间重量都成倍数关系。求最多能把几个砝码装入背包。

    前言

    (Jan 29th)刷题计划(5/6),算法标签:贪心。

    一道有技巧的贪心,一道挺有趣的题目。

    进制分解

    考虑题目中“砝码两两之间重量都成倍数关系”这句话肯定有猫腻,必然要以它为入手点。

    将砝码按重量排序并去重后,易知每一个砝码重量至少是前一个砝码的两倍,因此砝码重量的种数总共也只有(log_2(10^9)≈30)种,是非常少的。

    设排序去重后第(i)种砝码重量为(a_i),个数为(b_i)

    我们定义一个特殊的进制,其中第(i)位的位权是(a_i)

    然后我们把背包的容量都按照这种特殊的进制进行进制分解,然后分每一位加在一起。注意,加的过程中不能进位,因为每个背包是独立的。

    最后,我们贪心地从小到大枚举每一种砝码。

    对于第(i)种砝码,我们操作(b_i)次,每次将第(i)位减(1)。若减成了负数,则去向更高位借位。若无法再借,就说明无法再加砝码。

    注意,第(i+1)位的(1)退到第(i)位,会变成(frac{a_{i+1}}{a_i})

    具体实现详见代码。

    代码

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 100000
    using namespace std;
    int n,m,k,s[N+5],a[N+5],b[N+5],p[N+5];
    I bool Dec(CI x)//将第x位减1
    {
    	RI i;for(i=x;i<=k&&!p[i];++i);if(i>k) return 0;//如果借不到,返回0
    	for(--p[i--];i>=x;--i) p[i]+=a[i+1]/a[i]-1;return 1;//借位,返回1
    }
    int main()
    {
    	RI i,j,t=0;for(scanf("%d%d",&n,&m),i=1;i<=n;++i) scanf("%d",s+i);
    	for(i=1;i<=m;++i) scanf("%d",a+i);sort(a+1,a+m+1);//排序
    	for(i=1;i<=m;++i) a[i]^a[i-1]?(a[++k]=a[i],b[k]=1):(++b[k]);//去重,同时统计每种砝码的个数
    	for(i=1;i<=n;++i) for(j=k;j;--j) p[j]+=s[i]/a[j],s[i]%=a[j];//进制分解
    	for(i=1;i<=k;++i) for(j=1;j<=b[i];++j) if(Dec(i)) ++t;else goto End;//枚举砝码尝试放入
    	End:return printf("%d",t),0;//输出答案
    }
    
  • 相关阅读:
    ClickOnce發布經驗
    reporting Server組件不全引起的致命錯誤
    異步調用
    Usercontrol Hosted in IE
    MATLAB命令大全(转载)
    一种保护眼睛的好方法
    关于oracle自动编号
    An Algorithm Summary of Programming Collective Intelligence (1)
    An Algorithm Summary of Programming Collective Intelligence (3)
    An Algorithm Summary of Programming Collective Intelligence (4)
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/BZOJ1110.html
Copyright © 2011-2022 走看看