zoukankan      html  css  js  c++  java
  • 【好题】dp降维转化+数学+贪心——cf1348E

    这题dp的状态设计值得学习,由于多状态复杂度会爆炸,所以考虑降维

    如果可以用一个维度求出另一个维度的状态(即两个维度的值可以看做是绑定在一起的),那么就可以降下一维了

    这题还有点卡常。。评测机快就能跑过去。。

    /*
    很容易想到用dp[i][j][k]来表示前i棵树,留下j个红果子,k个蓝果子状态下可以装满的最大篮子数
    但是复杂度为nk^4,所以想办法优化掉一维
    
    可以推出一个结论:每棵树最多只有一篮子是混色的 
    其实只需要考虑红果子的余数即可,dp[i][j]表示前i棵树,红果子余下j个的最大篮子数,
        此时前i棵树蓝果子的余数是可以算出来的 sum[i]-dp[i][j]*K-j 
    那么枚举第i+1棵树混色篮子的红果子树x,对应蓝果子数K-x
    余下所有红果子数 last1=j+a[i+1]-x
    余下所有蓝果子数 last2=(sum[i]-dp[i][j]*k-j)+(b[i+1]-(k-x))
    要更新的状态就是dp[i+1][last1%K]    
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define N 505
    #define ll long long 
    
    ll n,k,a[N],b[N],sum[N],dp[N][N];
    
    int main(){
        cin>>n>>k;
        for(register  int i=1;i<=n;i++)scanf("%lld%lld",&a[i],&b[i]);
        for(register  int i=1;i<=n;i++)
            sum[i]=sum[i-1]+a[i]+b[i];
        memset(dp,-1,sizeof dp);
        dp[0][0]=0;
        
        for(register int i=0;i<n;++i){
            for(register  int j=0;j<k;++j)if(dp[i][j]>=0){
                //没有混色篮子
                ll last1=j+a[i+1];
                ll last2=(sum[i]-dp[i][j]*k-j)+b[i+1]; 
                dp[i+1][last1%k]=max(dp[i+1][last1%k],dp[i][j]+last1/k+last2/k);
                
                for(register  int x=1;x<k;++x)if(x<=a[i+1] && (k-x)<=b[i+1]){
                    ll last1=j+a[i+1]-x;
                    ll last2=(sum[i]-dp[i][j]*k-j)+(b[i+1]-(k-x));
                    dp[i+1][last1%k]=max(dp[i+1][last1%k],dp[i][j]+1+last1/k+last2/k);
                }
            }
        }
        
        ll mx=0;
        for(register  int j=0;j<k;++j)
            mx=max(mx,dp[n][j]);
        cout<<mx<<'
    ';
    }
      
  • 相关阅读:
    如何使用android模拟器截图
    android SD卡文件的读写
    res/raw下的资源文件读写
    window 运行指令(1)
    javax.swing.JOptionPane.showMessageDialog() 方法
    Eclipse快捷键
    EditPlus怎样自动换行
    java的HashCode方法
    eclipse汉化全程
    (转载)jdbc事务处理
  • 原文地址:https://www.cnblogs.com/zsben991126/p/12893261.html
Copyright © 2011-2022 走看看