zoukankan      html  css  js  c++  java
  • code1047 邮票面值设计

    dfs+dp

    dfs枚举每种情况,每层递归确定第k个数i:i = a[k-1]+1 to a[k-1]*n+1

    当枚举完一个序列时,使用check()测试它能达到的max

    使用dp。设dp[i]为凑成面值为i的最少张数

    for(int k=1;a[k]<=i&&k<=t;k++){
        if(dp[i-a[k]]<n){
            dp[i]=min(dp[i], dp[i-a[k]]+1);
        }
    }

    注意dp[i]一开始要设成最大值

    代码如下:

    #include<iostream>
    #include<cstring>
    #define Size 41
    using namespace std;
    
    int a[Size];
    int dp[10005];
    int best[Size];
    int n,t;//n张 t种 
    int num=0;void save(int x){
        num=x;
        for(int i=1;i<=t;i++){
            best[i]=a[i];
        }
    }
    
    int check(){
        //memset(dp,0x3f,sizeof(dp));
        dp[0]=0;
        int ans=0;
        bool ok=true;
        
        //for(int i=1;i<=t;i++)cout<<a[i]<<" ";
        //cout<<endl;
        
        for(int i=1;ok;i++){
            ok=false;
            dp[i]=0x3f3f3f3f;
            for(int k=1;a[k]<=i&&k<=t;k++){
                if(dp[i-a[k]]<n){
                    dp[i]=min(dp[i], dp[i-a[k]]+1);
                    ok=true;
                }
            }
            if(ok)ans=i;
            
            //cout<<dp[i]<<' ';
        }
        //cout<<endl<<endl;
        
        return ans;
    }
    
    void dfs(int k){if(k>t){
            int x=check();
            if(x>num)save(x);
            return;
        }
        
        for(int i=a[k-1]+1;i<=n*a[k-1]+1;i++){
            a[k]=i;
            dfs(k+1);
        }
    }
    
    int main(){
        cin>>n>>t;
        
        a[1]=1;
        num=1;
        
        dfs(2);
        
        for(int i=1;i<=t;i++){
            cout<<best[i]<<' ';
        }
        cout<<endl<<"MAX="<<num<<endl;
        cout<<f;
        return 0;
    } 

    By the way:a[1]一定是1!

    PS:你可以看到我把check的第一行memset注释掉了,因为大部分时候很长的dp数组后面的很多元素都没有用(max没有那么大),所以只需要在循环里用到一个写一个dp[i]=x03f3f3f3f就可以了。memset使程序变得很慢很慢。(真的很慢啊...)(你真的不需要再试它有多慢了,因为我已经花一个小时帮你试了无数遍了...)

    如果想继续优化,可以边dfs边维护dp和当前max2的值,这样dfs循环就可以写成这样:

    i = a[k-1]+1 to max2+1

    如果i>max2+1,那么max2+1这个数将始终无法凑成,结果不会更优

  • 相关阅读:
    Java——快速排序
    Java——归并排序
    Java——递归
    Java——希尔排序
    Java——插入排序
    Java——选择排序
    ES6快速入门
    ECharts is not Loaded
    scoped的规则
    css哪些样式属性可以继承
  • 原文地址:https://www.cnblogs.com/FuTaimeng/p/5456677.html
Copyright © 2011-2022 走看看