C/C++大学慕课的算法笔记(后续更新)



前言:
✌ 作者简介:CC++Edge淇,大家可以叫我--斯淇。(CSDN优质博客的建议加这一条)
📑 个人主页:CC++Edge淇主页
📫 如果文章知识点有错误的地方,请指正!和大家一起学习,一起进步👀
🔥 如果感觉博主的文章还不错的话,还请不吝👍关注、点赞、收藏三连支持👍一下博主哦
💬 人生格言:那个人应该是我!。💬

                                           🎉🎉欢迎持续关注🎉🎉

动态规划(——)

基本思路:1.把原问题分解为多个子问题!

2.确定状态:在动态规划中,往往将和子问题相关的各个变量的一组取值,称为一个“状态”。一个“状态 ”下的“值”,就是这个状态所对应子问题的解!(即数字所在的行列也就称为状态!)整个问题的时间复杂是状态数目乘以计算每个状态所需要时间!

3.确定一些初始状态(边界状态)的值!!

还有一点需要注意的是!(不是所有的问题都去尝试动态规划解决),他又使用的特点!1.问题具有最优结构性质2.无后效性!

动归的常用两种形式:

1)递归型:

优点:直观,同意编写

缺点:会爆栈,函数调用带来额外时间的开销!(个人觉得比递归慢一点)

2)递推型:效率高,有可能使用滚动数组节省时间

01背包问题

题目描述

一个旅行者有一个最多能装m公斤的背包,现在有n中物品,每件的重量分别是W1、W2、……、Wn,每件物品的价值分别为C1、C2、……、Cn, 需要将物品放入背包中,要怎么样放才能保证背包中物品的总价值最大?

提一提思路(动态规划):

  1. #include  
    int main(){  
        int sum,i,j,l,p;  
        sum(i,0)=sum(0,j)=0 //这个是原本!  
        sum(i,j)=sum(j-1,j);//当这个数小于总数时即为下降  
        sum(i,j)=max{sum(v-1,j),sum(i-1,j)+sum(i,j+1)+sum(i,0)}   
    }

这个时候就得看这个sum(i,j)该如何控制第一种原因:要么就没有分进去,第二种原因:这些物品被装进去了

参考一下优秀CSDN博主的代码!!!

  1. #include  
    #include  
      
    int V[100][100];//前i个物品装入容量为j的背包中获得的最大价值  
      
    int max(int a,int b){  
       if(a>=b)  
           return a;  
       else return b;  
    }  
       
    int KnapSack(int n,int weight[],int value[],int C){  
          
        //填表,其中第一行和第一列全为0,即 V(i,0)=V(0,j)=0;   
        for(int i=0;i
            V[i][0]=0;  
        for(int j=0;j
            V[0][j]=0;  
        //用到的矩阵部分V[n][C] ,下面输出中并不输出 第1行和第1列   
          
        printf("编号 重量 价值  ");  //菜单栏 1   
        for(int i=1;i
            printf(" %2d ",i);  
        printf("\n\n");  
                  
        for(int i=1;i
            printf("%2d   %2d   %2d     ",i,weight[i-1],value[i-1]);  //菜单栏 2 (weight与value都是从0开始存的,所以开始i=1时对应0的位置)  
              
            for(int j=1;j
                if(j//包的容量比该商品体积小,装不下,此时的价值与前i-1个的价值是一样的  
                    V[i][j]=V[i-1][j];  
                    printf("%2d  ",V[i][j]);  
                }  
                else{  //还有足够的容量可以装该商品,但装了也不一定达到当前最优价值,所以在装与不装之间选择最优的一个  
                    V[i][j]=max(V[i-1][j],V[i-1][j-weight[i-1]]+value[i-1]);          
                    printf("%2d  ",V[i][j]);  
                }  
            }  
            printf("\n");  
        }  
          
            return V[n][C];  
              
    }  
      
    void Judge(int C,int n,int weight[]){   //判断哪些物品被选中       
        int j=C;  
        int *state=(int *)malloc(n*sizeof(int));  
          
        for(int i=n;i>=1;i--){  
            if(V[i][j]>V[i-1][j]){  //如果装了就标记,然后减去相应容量   
                    state[i]=1;  
                    j=j-weight[i-1];  
                }  
            else  
                state[i]=0;  
        }  
        printf("选中的物品是:");  
        for(int i=1;i
            if(state[i]==1)  
                printf("%d ",i);  
        printf("\n");  
    }  
       
    int main(){  
      
        int n;        //物品数量   
        int Capacity;//背包最大容量  
          
        printf("请输入背包的最大容量:");  
        scanf("%d",&Capacity);  
          
        printf("输入物品数:");  
        scanf("%d",&n);  
          
        int *weight=(int *)malloc(n*sizeof(int));//物品的重量  
        int *value=(int *)malloc(n*sizeof(int)); //物品的价值  
          
          
        printf("请分别输入物品的重量:");  
        for(int i=0;i
            scanf("%d",&weight[i]);  
       
        printf("请分别输入物品的价值:");  
        for(int i=0;i
            scanf("%d",&value[i]);  
       
        int s=KnapSack(n,weight,value,Capacity);  //获得的最大价值  
          
        Judge(Capacity,n,weight);  //判断那些物品被选择   
       
        printf("最大物品价值为: ");  
        printf("%d\n",s);  
         
        return 0;  
    }  

算法2深度优先搜索

基本概念

深度优先搜索算法(Depth First Search,简称DFS):一种用于遍历或搜索树或图的算法。 沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所在边都己被探寻过或者在搜寻时结点不满足条件,搜索将回溯到发现节点v的那条边的起始节点。整个进程反复进行直到所有节点都被访问为止。属于盲目搜索,最糟糕的情况算法时间复杂度为O(!n)。

说一说思想:这个称为回溯法就相当于走一条路(比如一到二到三为一条路)走不通就直接往回走再重新走一次!尝试每一种可能

基本打法!!(先记住模板!)

  1. #include  
    int app(int i,int x) //这里放进去参数!  
    {  
        if(i>x)  
        return 1;  
        else   
        return 2;   
     }   
     void dfs(int step,int k,int q){  
        if(step==1){  
            k=1;  
         }  
         //输出每一种可能!  
         {  
            q++;  
             //每次进行一次标记!!  
             return 0;   
          }   
     }        
    return 0;  
    }   

找个列题玩玩!!

1.油田问题

问题:GeoSurvComp地质调查公司负责探测地下石油储藏。 GeoSurvComp现在在一块矩形区域探测石油,并把这个大区域分成了很多小块。他们通过专业设备,来分析每个小块中是否蕴藏石油。如果这些蕴藏石油的小方格相邻,那么他们被认为是同一油藏的一部分。在这块矩形区域,可能有很多油藏。你的任务是确定有多少不同的油藏。

input: 输入可能有多个矩形区域(即可能有多组测试)。每个矩形区域的起始行包含m和n,表示行和列的数量,

1

output: 对于每一个矩形区域,输出油藏的数量。两个小方格是相邻的,当且仅当他们水平或者垂直或者对角线相邻(即8个方向)。

  1. #include  
    char p[100][100];//要么是*代表没有油要么是@表示有油  
    int i,k,sum,num,o,m,n;  
    int a[8][2]={{1,0},{-1,0},{0,1},{0,-1},{1,1},{-1,-1},{-1,1}};  
    int check(int x,int y){  
    if(x>=0&&x=0&&y'@')   
    return 1;  
    else   
    return 0;  
    }  
    int dfs(int x,int y){  
        int i,sum,num,app;  
        if(check(x,y)){  
        p[x][y]='#';  
        for(i=0;i
            sum=x+a[i][0];  
            num=y+a[i][1];  
            dfs(sum,num);  
        }  
        return 1;  
        }  
        return 0;  
    }  
      
    int main(){  
        int  i,j,k;  
        while(scanf("%d %d",&m,&n)==2){  
            if(m==0&&n==0)  
         break;  
            o=0;  
        for(i=0;i
            scanf("%d",a[i]);  
            for(i=0;i
                for(j=0;j
                    if(dfs(i,j)){  
                        o++;  
                    }  
                }  
            }  
            printf("%d\n",o);  
        }   
        }  
        return 0;  
    }  

这里说一说广搜与深搜的比较

1.广搜一般用于状态表示比较简单、求最优策略的问题!

优点:他更像是一种完备策略(类似与万能解法)只有有问题就一定会有解答,而且,广度优先搜索找到的解,它还是最优的解法!!

但是它有一个缺点:就是太乱了(盲目性太强),尤其是当它与目标相比较靠近的时候,做了太多无用的搜索,占用的时间和空间会比较多(有些题目限制时间需要有慎重考虑)

2.深度搜索可以说基本上适用于大多数问题!

(只需要保持从起始状态下开始到末端状态下结束!)

贪心算法!!!!!

贪心算法的定义:

贪心算法是指在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,只做出在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。

解题的一般步骤是(基本思路)

1.建立数学模型来描述问题;

2.把求解的问题分成若干个子问题;

3.对每一子问题求解,得到子问题的局部最优解;

4.把子问题的局部最优解合成原来问题的一个解;

例题!!

设有M台完全相同的机器运行N个独立的任务,运行任务i所需要的时间为ti,要求确定一个调度方案,使得完成所有任务所需要的时间最短。假设任务已经按照其运行的时间从大到小来排序,算法基于最长运行时间作业优先的策略:按顺序先把每个任务分配到一台机器上,然后将剩余的任务一次放入最先空闲的机器。

  1. #include  
    void  app(int x,int y,int *m){  
        int num,k,l,q,i,j;  
    int a[50][50],p[100],sum[100];  
        for(i=0;i
        p[i]=0;  
            for(j=0;j
                a[i][j]=1;  
            }  
        }   
            for(i=0;i
                a[i][0]=i;  
            p[i]+=m[i];  
                sum[i]=1;  
            }  
            for(i=x;i
                num=p[0];  
                k=0;  
                for(j=0;j
                    if(num>p[j]){  
                        num=p[j];  
                        k=j;  
                    }  
                }  
                a[i][sum[k]]=i;  
                sum[k]+=1;  
            p[k]=p[k]+m[i];  
            }   
            for(i=0;i
                if(num
                    num=p[i];  
                }  
            }  
              
        printf("完成所有任务需要的时间:%d\n",num);  
            for(i=0;i
            printf("%d",i);  
            }  
            for(j=0;j
                if(a[i][j]==1){  
                    break;  
                }  
                    printf("%d\t",m[a[i][j]]);  
            }  
            printf("\n");  
          
              
    }  
    void main(){  
        int time[7]={16,14,6,5,4,3,2} ;  
        app(3,7,time);  
          
      
          
    }   

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员阿龙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值