dp之背包总结篇

Qlib数据获取避坑指南:从CSV导入到自定义数据源的完整解决方案 本文详细解析了Qlib数据获取的完整解决方案,从CSV导入到自定义数据源,涵盖了股票数据处理的关键技巧和常见陷阱。特别针对Qlib平台的数据格式要求和复权处理提供了实用指南,帮助量化投资者高效整合Wind等第三方数据源,确保数据质量与模型性能。 阅读详情

//新手DP学习中 = =!!

前言:背包问题在dp中可以说是经典,作为一个acmer,到现在才正式学习dp,可以说是比较失败的。我个人比较认同一点,想要做一个比较成功的acmer,dp、搜索、数学必须精练,比较遗憾的是,对我我自身而言,并没有早早的认识到这个问题,不过现在知道了,还有一年,也不算晚。还有,我建议学背包的童鞋,都看背包九讲......

dp之01背包

01背包,做为背包中最基础的一类背包,必须要掌握好,当然我这里说的掌握好,并不是说,你横扫hdu或者poj等oj上01背包模板题就可以的,记得很久以前,刚开始做背包问题,一天在hdu水了七八道,就自以为背包就是个模板,唉,真心不知道当时的自己是有多肤浅..........


01背包的动态转移方程,背包九讲上有详细的讲解,这里不再复述,就想说下,一维的和二维的转移方程都需要深刻理解,不要觉得任何时候01背包都可以转化为1维的数组


dp[i][j]=max(dp[i-1][j],dp[i-1][j-v[i]]+val[i]);

dp[j]=max(dp[j],dp[j-v[i]]+val[i]);


此外,还想说下,01背包为什么体积要从v---0?这个问题,背包九讲上是说可以每件物品只拿一次,恩,我觉得可以自己推推,这样理解会更加深刻.......


1、UVA624(记录路径问题)

总得来说,不管是01背包还是完全背包,其动态转移每次只有两种状态在转移,就说这道题目,

dp[i][j]=max(dp[i-1][j],dp[i-1][j-v[i]]+val[i])    对于dp[i][j]来说,它只能使由两个状态中的一个转移过来的,要么取一件,要么不取,那么我们再开一个二维数组s[i][j],0表示不取,1表示取,那么不取是dp[i-1][j],取是dp[i-1][j-v[i]]+val[i];这样,数组s[i][j]就记录下了每次动态转移的方向,在递归调用,打印路径,结果就出来了,具体可以看http://www.cnblogs.com/ziyi--caolu/archive/2013/04/10/3012578.html


2、UVA562(平分钱币问题)

题目大意:给定n个硬币,要求将这些硬币平分以使两个人获得的钱尽量多,求两个人分到的钱最小差值。

这类问题的关键就在平衡,而就这到题目而言,01背包本身求的就是在体积小于等于sum的情况下的最大值,那么这些硬币本身既当体积又当价值,把总价值求出来/2,再套用模板......可以说比较水的平衡问题,具体看:http://www.cnblogs.com/ziyi--caolu/archive/2013/04/10/3012755.html


3、组成n块钱,有多少种的问题

这类题目,一般是这样描述的:给你n块钱,有m种钱币,每种钱币只能用一次,问组成n块钱有多少种方法........

对于这类题目,我更多的感受是觉得是到递推题,其实,有好多的dp都是一个递推,然后记录更新状态的过程,要组成dp[j],那么假设有一个5快的钱币,那么首先要判断dp[j-5]有没有组成,这里我比较喜欢用0表示没有这个状态,>0表示这个状态存在,那么在初始化dp数组的时候,dp[0]=1;然后套用背包模板,其动态转移方程(倒不如说递推式)为dp[j]+=dp[j-5];

  上面是常规题目,下面为01背包的变种题:



4、poj2184(两个属性最大和,平移问题)

题意:给定两个属性,求这两个属性的和的最大值.........

思路:对于这种题目,我们可以尝试将一个属性当作容量,另一个属性当作价值,然后考虑dp.......这个题目属性还可以是负数,那么可以采取平移1000个单位,使其不存在负数问题。将第一个属性往后平移1000个单位,然后推导其动态转移方程,若是dp[i],代表当加入第一个属性加到i时,符合题意的第二个属性的最大值......题意是两个属性的和的最大值,那么动态转移方程必然不是dp[j]=max(dp[j],dp[j-s[i][0]]+s[i][1]),

因为这个动态转移方程固然可以求出第二个属性的最大值,但别忘了题意要求第一个属性与第二个属性的和的最大值,那么,第一个属性平移了1000个单位,在考虑动态转移时,是必须要将这个考虑进去的。可以开一个a数组记录路径,然后根据题意,
动态转移方程应该为dp[j]=max(dp[j]-a[j]*1000,dp[j-s[i][0]]+s[i][1]-(a[j-s[i][0]]+1)*1000),一开始a数组全部赋值为0,所以需要a[j-s[i][0]]+1.....因为它新加入了一个值。考虑这个方程,dp数组的初始全部赋值为负无穷大,dp[0]=0。

注意一点,在历遍查找最大值的时候,dp[i]>0,i-a[i]*1000>0


 5、hdu2639(第k优解问题)

题意:给出一行价值,一行体积,让你在v体积的范围内找出第k大的值.......(注意,不要 和它的第一题混起来,它第一行是价值,再是体积)

思路:首先dp[i][j]代表的是在体积为i的时候第j优解为dp[i][j]......那么,我们就可以这样思考,i对应体积,那么如果只是一维的dp[i],代表的应该是体积为i时的最大值,那么同理,dp[i][1]代表的是体积为i时的最大值,那么我们就可以退出两种动态,dp[i][m],dp[i-s[i][0]][m]+s[i][1].....然后把这两种状态开个两个数组分别保存起来,再合并出体积为i时的前k优解......依次后推,直到dp[v][k].......


 6、hdu3644(带限制的01背包)

题意:买东西,每个东西有三个特征值,p代表价格,q代表你手中钱必须不低于q才能买这个物品,v代表得到的价值。

mark:又是变种01背包,每做一个变种的,就是一种提高。。

按照q - p以由大到小的顺序排序,然后进行01背包的DP即可。

 

 dp之完全背包

完全背包较之01背包,唯一区别就是01背包的物品每个只能取一次,而完全背包可以取无限次

dp[i][j]=max(dp[i-1][j],dp[i][j-v[i]]+val[i])

dp[j]=max(dp[j],dp[j-v[i]]+val[i]);

1、poj3181(高精度背包)

这道题目要用到大数加法,其他的没有什么难度,当然,你的大数加法如果写的比较挫,是会超时的......解题报告:http://www.cnblogs.com/ziyi--caolu/p/3211091.html


2、poj1787(多重背包转化为完全背包,以及路径记录   推荐)

题意:有四种硬币,1分,5分,10分,25分,分别有a,b,c,d种,给出一个n分钱,要求你求出组成n分钱最多需要的硬币数量,并且输出组成它的各种硬币的数量......

学到的东西:这个题目我是用两种方法做的,一个是完全背包,一个是多重背包。做完这个题目,我对背包的理解可以说上了个层次......还有记录路径的方法,反过来求出各个硬币的数量,都是我以前做的题目没有涉及到的.......

要求出各个硬币有多少种,只需要记录路径,在开一个数组统计p-path[p],为什么可以如此?很容易想到path[p]=p-v[i]


如此,p-path[p]==p-(p-v[i])==v[i],而v[i]正好是硬币的价值........这道题目令我思考到一个东西,一般的背包问题的初始值都是将dp全部赋值为0的,而在这边dp[0]==1,并且在动态转移的过程中,还限制了dp[j]>0才可以转移,与背包的模板的动态转移不同啊?为什么要这样呢?


在一般的dp题目里面,有体积,价值,所要求的不是最大价值就是最小价值,而定义的dp[i][j]意义是装有i件物品,体积为j的最大值为dp[i][j],简化为一维的dp[j]代表的是在体积为j的时候最大价值为dp[j]。仔细观察,可以发现,在dp[j-v[i]]时,dp[j]本身就可以从dp[j-v[i]]那边得到值,因为dp[j-v[i]]这个地方,它可以组成dp[j]......也就是说,它不需要去判断在dp[j-v[i]]前面是否有数可以组成dp[j-v[i]],因此dp[j-v[i]]为不为0,不影响最终结果......


而这个题目却不同,需要赋值dp[0]=1;在动态转移的时候还得保证dp[j-v[i]]>0,这是因为题意是要求组成n分钱需要的最多硬币数量,那么你要可以组成dp[n],dp[n-v[i]]必须要可以组成,否则就会出错.......同理,这道题目原理如此,在做给出n分钱,每种钱币有a,b,c,.....种,求组成n分钱最多的种数,也是要赋值dp[0]=1的,原理是一样的........

这告诫我,在做dp题目时,要仔细思考好其前后的关系,以及中间推导至最后的关系.....


 

 3、poj2063题意:求投资k年获得最大投资,每年都选最大利息的方案进行投资k年后就可以得到最多的人民币。
注意:每一年收到的利息都可以作为下一年的本金......其实从测试数据来看,是很好看出来的......
思路:将每一年的“体积”加上利息就好,当然,数据太大,可以除以100减少时间和空间复杂度......
解题报告:http://www.cnblogs.com/ziyi--caolu/p/3214100.html
 
dp之多重背包
 
1、hdu1114(水题)

2、hdu1059
题意:价值为1,2,3,4,5,6. 分别有n[1],n[2],n[3],n[4],n[5],n[6]个。求能否找到满足价值刚

好是所有的一半的方案。  思路:简单的多重背包,我建议多重背包都用二进制拆分优化下........ 解

题报告:http://www.cnblogs.com/ziyi--caolu/p/3216818.html
 

3、poj1217
题意:有现今cash,和n种钱币,每种钱币有ni个,价值为di,求各种钱币组成的不超过cash的最大钱数

.......

思路:二进制拆分转化为01背包,或者转化为完全背包都是可以的。

解题报告:http://www.cnblogs.com/ziyi--caolu/p/3216827.html


4、poj2392(推荐)

题意:有k种石头,高为hi,在不超过ai的高度下,这种石头可以放置,有ci种这个石头,求这些石头所能放置的最高高度.........

思路:以往的什么硬币种数,最大硬币数之类的,他们的硬币都已经是排好序了的,总是从小到大,但是这个题目不同,它有着最高高度的限制,那么在思考的时候,要得到最优的,那么首先就是要对ai排序......这是贪心,然后就是多重背包了........

 

 

多维背包 

1、hdu4501

 

思路:将v1,v2,k都当作一种体积,每种物品只能取一次,求max.......

 

反思:以前写背包,由于只有一个体积,所以习惯性的在for中,就所取的最小值限制,而在这次,因为这里导致wa了,具体是因为在多个体积限制的背包里,当这个体积小于它的最小体积时,它可以不去减它的最小体积,而是作为一种状态来传递其他体积的限制的值.......

解题报告:http://www.cnblogs.com/ziyi--caolu/p/3217151.html

2、hdu2159

解题报告:http://www.cnblogs.com/ziyi--caolu/p/3222683.html

3、hdu3496

题意:给你n张电影门票,但一次只可以买m张,并且你最多可以看L分钟,接下来是n场电影,每一场电影a分钟,b价值,要求恰好看m场电影所得到的最大价值,要是看不到m场电影,输出0;


思路:这个题目可以很明显的看出来,有两个限制条件,必须看m场电影的最大价值........其实我前面在01背包时提过,对于这样的条件,要可以看第n场电影,那么相对应的第n-1场电影必须看了,否则不能进行动态转移.......我的想法是,0代表着这场电影没有看,>0代表这场电影看了。其他的就是动态转移了,很容易得到,dp[i][j]=max(dp[i][j],dp[i-1][j-v[i]]+val[i])........当然,在最开始的dp[0][0]=1,那么得到的最大值会在第m场电影里面,最大值需要减去初始值........也就是1


 4、poj2576(推荐)

题意:有一群sb要拔河,把这群sb分为两拨,两拨sb数只差不能大于1,输出这两拨人的体重,小的在前面......

思路:把总人数除2,总重量除2,之后你会发现就是个简单的二维背包,有两个限制.....一个是人数,一个是体重,再仔细思考下,发现一定要有这么多人,也就是说一定要有总人数除以2这么多人,那么当第n个人存在,第n-1个人必须存在.........


 5、poj1837(天平问题  推荐)

题意:给你c(2<=c<=20)个挂钩,g(2<=g<=20)个砝码,求在将所有砝码(砝码重1~~25)挂到天平(天平长  -15~~15)上,并使得天平平衡的方法数.......


思路:(这是我木有想到的)将g个挂钩挂上的极限值:15*25*20==7500

那么在有负数的情况下是-7500~~7500   以0为平衡点......

那可以将平衡点往右移7500个单位,范围就是0~~15000......这样就好处理多了

其实我觉得以后的题目中不仅仅天平问题可以这样处理,在有负数的以及要装入数组处理的题目中,我们都可以尝试着平移简化问题......


这题目是要将所有的砝码都挂到天平上后的最多方法数,同时砝码自带质量,也就是说,这不仅仅有着“容量”的限制,还有着“件数”的限制,很明显的二维费用背包......

每个砝码只能用一次,果断01背包,并且在处理这一状态前,先判断前一状态是否存在......我喜欢用>0表示存在,用0表示不存在,而这个题目又是求方法数,不需要再减去1........


 分组背包

1、hdu1712

 

题意:有n门课程,和m天时间,完成a[i][j]得到的价值为第i行j列的数字,求最大价值......

 

思路:分组背包,就是第n门课程,可以做一天,可以做两天,但它们相斥,你做了一天,就不能再做一天...也就是不能再做这门课程了......

 

 

当然这是最多取一个的算法.......

 2、hdu3033(最少取一次   推荐)

题意:有n双鞋子,m块钱,k个品牌,(一个品牌可以有多种价值不同的鞋子),接下来n种不同的鞋子,a为所属品牌,b为要花费的钱,c为所能得到的价值。每种价值的鞋子只会买一双,有个人有个伟大的梦想,每个品牌的鞋子至少买一双,问他这个梦想可以实现不?不可以实现输出Impossible,可以实现输出最大价值......

思路:很容易看出来这是个分组背包题,当然这个分组背包有些不同于每组最多取一个的分组背包......但我是觉得,分组背包就这么几种问法吧

1、最常见的、最水的,每组最多取1个.........(一般是隐性的,需要自己分析)


2、每组至少取1个........(就是本题)


3、随意选,可以选,可以不选,可以只选1个,也可以选多个......(暂时还未学,马上会学).....

对于第一种,模板题,只要你可以分析出来,那么可以水过.....

对于第二种,我想说也是模板题,当然是以本题为基础的模板.........

好吧,这道题目,首先,每组至少取一个,就是说必须要取一个,那么数组dp[i][j],代表的含义就是 前i组容量为j的情况下所得到的最大价值为dpi][j];


同样的,我们首先思考它的状态,每组必须要取一个,那么第i组存在的情况下,第i-1组也必须存在,也是回到了前面所做背包所说的那种“一定”、“必须”的状态,那么同样的在动态转移的时候,要判断它的前一个状态合不合法,我个人比较喜欢用0来判断不合法,>0判断合法.......初始化dp[0][0]=1,最后得到的结果减去1......我想说的是,最后的结果不一定会集中在dp[k][m]上,因为这个状态它不一定存在,也就是说,这个状态不一定合法,当然,也没有关系,我们考虑第k组一定要存在,那么扫描下dp[k][i],取最大值就好.....

 

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
int dp[15][10005],s[105][2],num[15][105];
queue<int>Q[105];
int main()
{
    int n,m,k;
    while(scanf("%d %d %d",&n,&m,&k)>0)
    {
            
          for(int i=0;i<105;i++)
          while(!Q[i].empty())
          Q[i].pop();
          for(int i=1;i<=n;i++)
          {
               int a,b,c;
               scanf("%d %d %d",&a,&b,&c);
               Q[a].push(i);
               s[i][0]=b;
               s[i][1]=c;
          }
            
          for(int i=1;i<=k;i++)
          {
               int j=1;
               while(!Q[i].empty())
               {
                    num[i][j++]=Q[i].front();
                    //printf("i==%d %d\n",i,Q[i].front());
                    Q[i].pop();
               }
               num[i][0]=j;
          }                                 //前面都是将数据处理好
          memset(dp,0,sizeof(dp));       //初始化dp
          dp[0][0]=1;
          int flag=1;
          for(int i=1;i<=k;i++)        //这是分组
          {
              if(num[i][0]==1)        //要是有一组没有数据,那么说明,它不可能满足每组必须取一个这条件.......
              {
                    flag=0;
                    break;
              }
              for(int f=1;f<num[i][0];f++)     //不同于最多取一个的分组背包,这里是先放每组有的物品,后放容积.......
              {
                   int xx=num[i][f];;
                   for(int j=m;j>=0;j--)        //至于为什么这么放?我是认为,它是一种模板.......
                   {
                        if(j-s[xx][0]>=0&&dp[i][j-s[xx][0]]&&dp[i][j-s[xx][0]]+s[xx][1]>dp[i][j]) //这个判断必须放到第一,以免重复
                        dp[i][j]=dp[i][j-s[xx][0]]+s[xx][1];
                          
                        if(j-s[xx][0]>=0&&dp[i-1][j-s[xx][0]]&&dp[i-1][j-s[xx][0]]+s[xx][1]>dp[i][j])//这个必须放在上一个判断下面.....
                        dp[i][j]=dp[i-1][j-s[xx][0]]+s[xx][1];
                          
                   }
              }
          }
          int maxx=0;
          for(int i=0;i<=m;i++)
          if(maxx<dp[k][i])
          maxx=dp[k][i];
          if(maxx==0||flag==0)
          printf("Impossible\n");
          else
          printf("%d\n",maxx-1);//最大值记得减去1
    }
    return 0;
}


 

 3、hdu3535(必做,三种状态都有:最少取一次,最多取一次,随意取  推荐)


题意:有0,1,2三种任务,0任务中的任务至少得完成一件,1中的任务最多完成1件,2中的任务随便做。每一个任务最多只能做一次 。n代表有n组任务,t代表有t分钟,m代表这组任务有m个子任务,s代表这m个子任务属于0,1,2中的哪种类型,接下来是m个子任务,第一个数代表要花费的时间,第二个数代表得到的愉悦度......求在可以完成工作的情况的最大愉悦度....要是不能完成,输出-1(题意要求每个子任务只能被取一次)


错误思路:我一开始想,把0,1,2这三大组任务的子任务先统计好,在dp的时候,我开dp[3][105],代表在完成3组任务体积为105的情况的最大愉悦度.......这种思路是错的,因为题目给出的n组任务是有其固定顺序,只能是按照它给出来的解决问题.......


ac思路:分为n组,每一组判断这一组是属于0,1,2三种任务中的哪一组......

若是属于0,那么将这一组的dp[i][j],j从0~~t全部置为负无穷大,然后开始动态转移.....为什么要置为负无穷大?因为只有这样才能不出现一个都不选择的情况.....其动态转移方程,,在我前一个分组背包题目已经详细推导过,就是dp[i][j]=max(dp[i][j-v[i]]+val[i],dp[i-1][j-v[i]]+val[i],dp[i][j])


若是属于1,先将第i-1的状态传递到第i状态,在开始分组背包的模板......最多取一个dp[i][j]=max(dp[i-1][j],dp[i-1][j-v[i]]+val[i]);


若是属于2,先将第i-1的状态传递到第i状态,随意取,那么可以不取,取任意个子任务......dp[i][j]=max(dp[i-1][j],dp[i][j-v[i]]+val[i],dp[i-1][j-v[i]]+val[i]);

 

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
#define M -1000000000
int dp[105][105],s[105][2];
int main()
{
    int n,t;
    while(scanf("%d %d",&n,&t)>0)
    {
        int m,k;
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++)
        {
            scanf("%d %d",&m,&k);
            for(int j=1;j<=m;j++)
            scanf("%d %d",&s[j][0],&s[j][1]);
            if(k!=0)
            for(int j=0;j<=t;j++)        // 传递状态
            dp[i][j]=dp[i-1][j];
            if(k==0)                        //至少取一个 ,分组背包变形模板.......
            {
                for(int tmp=0;tmp<=t;tmp++)
                dp[i][tmp]=M;
                for(int tmp=1;tmp<=m;tmp++)  //这层for循环必须在前面......
                {
                    for(int j=t;j>=0;j--)            
                    {
                        if(j-s[tmp][0]>=0&&dp[i][j-s[tmp][0]]+s[tmp][1]>dp[i][j])
                        dp[i][j]=dp[i][j-s[tmp][0]]+s[tmp][1];
                          
                        if(j-s[tmp][0]>=0&&dp[i-1][j-s[tmp][0]]+s[tmp][1]>dp[i][j])
                        dp[i][j]=dp[i-1][j-s[tmp][0]]+s[tmp][1];
                    }
                }
            }
            else if(k==1)               //最多取一个 ,分组背包模板
            {
                for(int j=t;j>=0;j--)
                {
                    for(int tmp=1;tmp<=m;tmp++)
                    {   
                        if(j-s[tmp][0]>=0)
                        {
                            if(dp[i-1][j-s[tmp][0]]+s[tmp][1]>dp[i][j])
                            dp[i][j]=dp[i-1][j-s[tmp][0]]+s[tmp][1];
                        }   
                    }
                }
            }
            else if(k==2)                     //随意取 ,01背包,每个子任务只能取一次,却可以取任意个不同的子任务
            {
                for(int tmp=1;tmp<=m;tmp++)
                {
                    for(int j=t;j>=s[tmp][0];j--)
                    {
                        if(dp[i][j-s[tmp][0]]+s[tmp][1]>dp[i][j])
                        dp[i][j]=dp[i][j-s[tmp][0]]+s[tmp][1];
                          
                        if(dp[i-1][j-s[tmp][0]]+s[tmp][1]>dp[i][j])
                        dp[i][j]=dp[i-1][j-s[tmp][0]]+s[tmp][1];
  
                    }
                }
            }
        }
        if(dp[n][t]<0)
        printf("-1\n");
        else
        printf("%d\n",dp[n][t]);
    }
    return 0;
}

 

混合背包

总得来说,混合背包很容易理解,就是有的物品只能取一次,有的物品能取无限次,有的物品取得次数有限制,这样的话分别对对应情况采用01、完全、多重背包即可。但是题目往往没有那么简单、赤裸裸的,让你一看就知道是混合背包的,比如说下面这道题:

poj1742

 

题意:给你价值为a1,a2.....的货币,每种有c1,c2.......个,求这些货币所能组成的价值小于等于m有多少个.....

 

思路:很像一道多重背包题?那我一开始的确是用多重背包的思路编写的......TLE了,原来其中隐藏着一个被我忽视的一个问题,当ai*ci>=m时,我们没有必要去拆分ci了,就直接把这种情况当作完全背包处理.......


#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int dp[100005],t[300][2];
int n,m;
int sum;
void deal1(int x)
{
        for(int j=m;j>=x;j--)
        if(dp[j-x]&&dp[j-x]+x>dp[j]&&dp[j-x]+x-1<=m)
        {
                if(!dp[j])   sum++;
                dp[j]=dp[j-x]+x;
        }
}
int main()
{
        
      while(scanf("%d%d",&n,&m)>0&&(n+m))
      {
           for(int i=1;i<=n;i++)
           {
                   scanf("%d",&t[i][0]);
           }
           memset(dp,0,sizeof(dp));
           dp[0]=1;
           sum=0;
           for(int i=1;i<=n;i++)
           {
                   scanf("%d",&t[i][1]);
                   if(t[i][1]*t[i][0]<m)
                   {
                        int k=1;
                        while(t[i][1]-k>0)
                        {
                            deal1(k*t[i][0]);
                            t[i][1]-=k;
                            k*=2;
                        }
                        deal1(t[i][1]*t[i][0]);
                    }
                    else
                    {
                        for(int j=t[i][0];j<=m;j++)
                        if(dp[j-t[i][0]]&&dp[j]<dp[j-t[i][0]]+t[i][0])
                        {
                            if(!dp[j])   sum++;
                            dp[j]=dp[j-t[i][0]]+t[i][0];
                        }
                    }
           }
           printf("%d\n",sum);
      }
      return 0;
}



此次的背包总结到此结束了,我是做完区间dp才来写这个总结的,dp说起来是很神奇,但是要是你可以推导出状态,根据状态设置好初始化,那么就不算是难......


朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。



Unity 工具 之 SoftMask软遮罩 实现 UI 边缘渐变过渡的简单使用介绍 目录Unity 工具 之 SoftMask软遮罩 实现 UI 边缘渐变过渡的简单使用介绍一、简单介绍二、Mask 实现的遮罩效果三、Soft Mask 实现遮罩效果四、 Soft Mask 的一些设置五、插件下载Unity 工具类,自己整理的一些游戏开发可能用到的模块,单独独立使用,方便游戏开发。 阅读详情

相关推荐

荔枝派Nano内核编译

上文编译好uboot之后,想刷内核和根文件系统进去。其实官方的网盘里面,已经有打包好的系统镜像,包含所有的东西,可以直接烧录进flash或者TF卡,但是都是基于winbond芯片的,国产的xt25f128b刷进去妥妥的。所以没办法,只能自己再动手重新编译内核了。(PS:搞的我都想直接买一片w25q128换上了,有点麻烦,希望官方直接涨价或者出两版就行,不然对新手不友好啊)

木子点灯的博客 546

算法学习之动态规划DP——背包问题

一维状态第i轮对体积为 3的物品进行决策,则f[7]由f[4]更新而来,这里的f[4]正确应该f[i-1][4],但从小到大枚举j这里的f[4]在第i轮计算却变成了f[i][4]。当逆序枚举背包容量j时,我们求f[7]同样由f[4]更新,但由于是逆序,这里的f[4]还没有在第i轮计算,所以此时实际计算的f[4]仍然是f[i - 1][4]。在二维情况下,状态f[i][j]是由上一轮i - 1的状态得来的,f[i][j]与f[i - 1][j]是独立的。这Si个数分别为2^0, 2^1, 2^2……

m0_72955669的博客 5924

Part03 数据结构

本文介绍了CSP-S初赛中常见的高级数据结构及其实现,包括: 线性结构:双端栈、双端队列、单调队列、优先队列和ST表,重点分析了它们的特点、时间复杂度及典型应用场景。 集合与森林:并查集(带路径压缩和按秩合并)和树的孩子兄弟表示法,展示了多叉树转化为二叉树存储的方法。 特殊树结构:包括二叉堆、树状数组、线段树和字典树,详细说明了它们的构建、查询和更新操作,特别强调了线段树的递归实现和字典树的前缀匹配特性。 每种数据结构都配有核心C++代码实现,涉及数组模拟、动态规划和树形结构等编程技巧,适合算法竞赛选手快速

weixin_43863957的博客 1179

DP背包问题

最近学习了动态规划,网课上大佬们讲得我怎么都听不太懂???一听不懂就想摸鱼了...所以干脆不听课了,在这里整理一下经典DP题目。 一. 01背包问题 题目:P1048 [NOIP2005 普及组] 采药 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 01背包问题中,每个物品只有一件,换句话说,每件物品只有取(1)和不取(0)两种状态。 二维数组解决方法: 原理: ——引自《算法竞赛——从入门到进阶》 表格中第一维度i:待取背包的种类,第二维度j:待取背包的容量 ..

打发人间白云的博客 2218

Wi-Fi协议栈深度解析:从芯片实现到开源替代方案

本文深度解析Wi-Fi协议栈的架构与实现,对比了HardMAC与SoftMAC两种芯片方案的优劣。通过剖析ESP32等芯片的逆向工程实践,揭示了从零构建开源Wi-Fi MAC驱动(如esp32-open-mac项目)的技术路线与挑战,并探讨了开源协议栈对安全审计、功能定制和生态发展的重要意义。

weixin_29214335的博客 225

告别枯燥的Unity编辑器脚本:Odin插件如何让游戏数据配置变得像搭积木一样简单?

本文详细介绍了Odin插件如何简化Unity编辑器脚本开发,使游戏数据配置变得直观高效。通过声明式特性和丰富的可视化工具,Odin让开发者告别繁琐的OnGUI代码,实现所见即所得的开发体验。文章重点展示了Odin的核心优势、魔法特性及实战案例,帮助Unity开发者提升工作效率。

weixin_28717411的博客 345

背包九讲(dp问题详解)

【代码】背包九讲(dp问题详解)

weixin_64394633的博客 2191

六自由度机器人(机械臂)运动学建模及运动规划系列(四)——轨迹规划

本篇介绍了六轴机器人关节空间以及笛卡尔空间轨迹规划的简单方法,并给出了一种几何解法,以简化规划过程,并提供了简单的Matlab轨迹规划函数介绍。

weixin_47849087的博客 5万+

memset用法理解

memset用法理解 1.使用cstring头文件 2.可用于数组快速初始化 3.将数字以单个字节逐个拷贝的方式放到指定的内存中 对每个字节赋值,而int型有四个字节:memset(dp,0,sizeof(dp)); 赋值出来是00000000 00000000 00000000 00000000即十进制的0;memset(dp,-1,sizeof(dp)); 赋值出来是1111111...

yvonnewang9的博客 558

Qt C++ 串口调试助手

1. **串口配置**:支持自动检测可用串口,可配置波特率(9600~921600)、数据位(5~8)、校验位(无/奇/偶/标记/空格)、停止位(1/1.5/2)。- HEX 模式发送时,输入格式需为十六进制字符(0-9、A-F),可带空格(如 `01 A3 FF`)或不带空格(如 `01A3FF`)。// 发送模式:true=HEX,false=ASCII。// 字符串转HEX字节数组。ui->parity->addItems({"无", "奇校验", "偶校验", "标记校验", "空格校验"});

寒寒豆豆软件公司的博客 144

20 Embedding 与向量检索:语义为什么能变成距离

Embedding 是 RAG 语义检索的数学基础。本文用工程视角讲清文本如何变成向量,为什么语义相近会表现为距离相近,Top-K 检索如何工作,以及在模型选择、同模型约束、精确匹配和召回评估上的常见坑。

老于的笔记的专栏 6202

背包问题-DP动态规划

01背包问题 题目 思路 代码 01背包问题的最优方案 题目 思路 代码 完全背包问题 题目 思路 代码

weixin_74092648的博客 1381

架构师之HBase vs MongoDB 技术选型与场景决策实战案例

面对海量数据和高并发查询,该选 HBase 还是 MongoDB?本文为你提供完整的决策框架!从数据模型对比、架构解析、六大真实场景(电信 CDR、金融行情、广告点击流、电商商品、社交档案、内容管理)到性能、一致性、运维全面对比,助你在 PB 级时序数据和灵活查询之间做出精准选择!

肖哥弹架构博客 1097

DP之01背包问题(看这篇就完事)

用二维数组f[i][j]来表示前i个物品,背包容量j下的最优解,当背包容量为j的时候,如果j小于当前i的体积,那对应的以i的物品位置、j的背包容量下的最大价值为上一个i的最大容量,即f[i][j]=f[i-1][j];(2)放入第i个物品,剩余的背包容量变为j-v[i],此时的价值是f[i-1][j-v[i]]+w[i](即前i-1个物品,背包容量为j-v[i]时的最优解,再加上第i个物品的价值w[i])。f[j-v[i]]+w[i]表示放入第i个物品后,背包容量为j时的最大价值。

2301_80170790的博客 2841

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

DP浅解(背包篇)

背包问题

m0_69075795的博客 192

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

DP学习篇 0-1背包

利用两种动态规划思路求解0-1背包问题

SpaceTravellers的博客 121

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

从零备战蓝桥杯——动态规划(背包dp篇)

01背包,完全背包,多重背包~及相关练习题

c0re的博客 3581

【蓝桥杯准备打卡-基础算法笔记DP篇】-3.【多重背包】

就是01背包的思路了

m0_55653575的博客 300

Leetcode动态规划篇(0-1背包问题一维和二维dp实现)

🤓情况描述:有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i],得到的价值是value[i]。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。每一件物品其实只有两个状态,取或者不取。举一个例子,之后我们将拿这里例子进行后续分析物品weightvalue物品0115物品1320物品2430。

Jing_Hua 1067

DP背包小结(2)(结构完整,内容简洁,状态方程篇)

0 背包小结2,以下状态转移代码,假设所有相关变量及数组都已初始化,物品对应体积和价值都从下标为1的数组开始存储,dp[]或者dp[][]是各个状态下的背包内所装物品 1 01背包(背包总容纳bag,有type种物品,每种物品只有一个选择放还是不放,给出对应体积vlume[i]、对应价值value[i]) 1)二维数组(建议充分理解,而不用之做题)(因为容易忘记将因体积原因放不进去

他的博客 657

【蓝桥杯准备打卡-基础算法笔记DP篇】-4.【分组背包问题】

多重背包: 分成若干组,每组内有同种价值,体积的 物品,物品数量题目给定,选择k个该物品进入背包。

m0_55653575的博客 691

【蓝桥杯准备打卡-基础算法笔记DP篇】-1.【01背包】

01背包问题

m0_55653575的博客 501

【蓝桥杯准备打卡-基础算法笔记DP篇】-2.【完全背包】

完全背包问题的文章

m0_55653575的博客 532

第43天-DP-第九章 ● 139.单词拆分 ● 关于多重背包,你该了解这些! ● 背包问题总结篇!

代码随想录链接背包的种类背包的递推公式问背包是否能够装满 或者 最多可以装多少 max(dp[j], dp[j-i] + value[i])装满背包有多少种方法: dp[j] += dp[j-i]背包装满的最大价值: dp[j] = max(dp[j], dp[j-weight[i]]+value[i])装满背包的最小数: dp[j] = min(dp[j-coins[i] +1, dp[j])遍历顺序01背包。

weixin_43664712的博客 655
上一篇: HDU 4501
下一篇: FZU 2157 树形DP
Tyuio28
博客等级 码龄11年 12粉丝 279原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值