zoukankan      html  css  js  c++  java
  • [TC13761]Mutalisk

    [TC13761]Mutalisk

    题目大意:

    (n(nle20))个坏人,第(i)个坏人的血量为(A_i(A_ile60))。你可以每次攻击(3)个坏人,并分别造成(9)点、(3)点、(1)点伤害。问最少需要多少次攻击使得所有坏人血量都(le0)

    思路:

    二分+DP。

    (f_{i,j,k})表示前(i)个坏人,还有(j)次扣(9)点血的机会、(k)次扣(3)点血的机会,最多还能有几次扣(1)点血的机会。

    源代码:

    #include<vector>
    #include<cstring>
    class Mutalisk {
    	private:
    		static constexpr int N=21,M=101;
    		int n,a[N],f[N][M][M];
    		void upd(int &a,const int &b) {
    			a=std::max(a,b);
    		}
    		bool check(const int &m) {
    			memset(f,-1,sizeof f);
    			f[0][m][m]=m;
    			for(register int i=1;i<=n;i++) {
    				for(register int j=0;(j-1)*9<=a[i]&&j<=m;j++) {
    					for(register int k=0;(j-1)*9+(k-1)*3<=a[i]&&j+k<=m;k++) {
    						const int l=std::max(a[i]-j*9-k*3,0);
    						if(j+k+l>m) continue;
    						for(register int a=j;a<=m;a++) {
    							for(register int b=k;b<=m;b++) {
    								upd(f[i][a-j][b-k],f[i-1][a][b]-l);
    							}
    						}
    					}
    				}
    			}
    			for(register int i=0;i<=m;i++) {
    				for(register int j=0;j<=m;j++) {
    					if(f[n][i][j]!=-1) return true;
    				}
    			}
    			return false;
    		}
    	public:
    		int minimalAttacks(std::vector<int> x) {
    			n=x.size();
    			for(register int i=1;i<=n;i++) {
    				a[i]=x[i-1];
    			}
    			int l=1,r=100;
    			while(l<=r) {
    				const int mid=(l+r)>>1;
    				if(check(mid)) {
    					r=mid-1;
    				} else {
    					l=mid+1;
    				}
    			}
    			return r+1;
    		}
    };
    
  • 相关阅读:
    1. 二分查找
    Filezilla使用
    正则表达式regex
    TCP的三次握手和四次挥手
    Pycharm 更换源
    寒假学习进度(十四)
    寒假学习进度(十)
    寒假学习进度(九)
    寒假学习进度(八)
    寒假学习进度(七)
  • 原文地址:https://www.cnblogs.com/skylee03/p/9709282.html
Copyright © 2011-2022 走看看