zoukankan      html  css  js  c++  java
  • 部分和问题

    0-1部分和

    • 问题描述:有n个大小不同的数字a,判断是否能从中取出若干个数,使得这些数的和为k。
    • 解决思路:利用DFS(深度优先搜索)来解决,用dfs(i,j)表示前i个数字能否得到部分和j,则根据前i+1个数的能否得到部分和j或j+a[i+1]来判断dfs(i,j)的状态,算法如下:
    1 bool dfs(int i,int sum)
    2 {
    3     if(i==n) return sum==k;
    4     if(dfs(i+1,sum)) return true;
    5     if(dfs(i+1,sum+a[i+1])) return true;
    6     return false;
    7 }

      或者也可以将此问题转化为0-1背包问题求解,第i件物品的重量和价值均为a[i],判断能否恰好将某些物品放入容量为k的背包中。

    多重部分和

    • 问题描述:有n个大小不同的数字a,每个数有m个,判断能否从中取出若干个数,使得这些数的和为k。
    • 方法1:利用动态规划求解,dp[i][j]表示前i个数能否构成部分和j,时间复杂度为O(nkm)算法如下:
    1 dp[n+1][k+1];
    2 dp[0][0]=1;
    3 
    4 for(int i=0; i<n; i++)
    5     for(int j=0; j<=k; j++)
    6         for(int s=0; s<=m[i]&&s*a[i]<=j; s++)
    7             dp[i+1][j] |= dp[i][j-s*a[i]];
    • 方法2:利用动态规划求解,dp[i][j]表示用前i个数得到部分和时,第i个数最多能剩余多少个,dp[i][j]被初始化为-1,dp[i][j]>-1表示前i个数能得到部分和j,算法的伪代码如下:
      if dp[i-1][j]>=0 
          dp[i][j]=m[i];
      else if(a[i]>j || dp[i][j-a[i]])<=0) dp[i][j]=-1;
      else dp[i][j]=dp[i][j-a[i]]-1;

      对以上算法可以优化空间复杂度,用cn[j]表示状态dp[i][j],则算法如下:

      1 memset(cn,-1,sizeof(cn));
      2 dp[0]=0;
      3 
      4 for(int i=0; i<n; i++)
      5     for(int j=0; j<=k; j++)
      6         if(dp[j]>=0) dp[j]=m[i];
      7         else if(j<a[i] || dp[j-a[i]]<=0) dp[j]=-1;
      8         else dp[j]=dp[j-a[i]]-1;
  • 相关阅读:
    解决ecshop进入后台服务器出现500的问题
    Java8新特性(拉姆达表达式lambda)
    使用Optional优雅处理null
    Arrays.asList 存在的坑
    Java提供的几种线程池
    冒泡排序及优化详解
    如何让MySQL语句执行加速?
    关于https的五大误区
    127.0.0.1和0.0.0.0地址的区别
    宽带网络技术-大题重点
  • 原文地址:https://www.cnblogs.com/leeshine/p/4330298.html
Copyright © 2011-2022 走看看