蓝桥算法大总结

蓝桥算法大总结:

一般解决问题最简单的算法:除简单逻辑处理之外,还有暴力、枚举是最重要的

暴力、枚举(一般是多重循环、注意边界、添加标志位可以加快解题)

    while(scanf("%d",&n)!=EOF)
    {
        for( i = 0 ; i < n ; i++)
            scanf("%d",&len[i]);
        ans = -1;
        for( i = 0 ;i < n;i++)
            for( j = i+1 ; j < n ; j++)
                for( k = j+1; k < n; k++)
                    {
                    if(len[i]*len[i]+len[j]*len[j]==len[k]*len[k])  //枚举出有直角三角形成立
                        if(0.5*len[i]+len[j]>ans)
                            ans = 0.5*len[i]*len[j];
                    }
    }

怎么说呢,就是无限的for它就对了,然后注意边界值和出口

(for必达)

其实枚举也有好坏,数据不大的情况下就无脑枚举,如果算法超时了。。。但又没有更好的算法

可以尝试优化你的枚举

形如:


    int x,y,z;
    for(x = 1 ; x<=20;x++)
        for(y = 1 ; y <=33 ; y++)
            for(z = 1;z <= 100;z++)
                if(x+y+z == 100 && 5*x+3*y+z/3 == 100 )
                {
                  printf("公鸡数量=%d\t",x);
          printf("母鸡数量=%d\t",y);
          printf("雏鸡数量=%d\n",z);
                }
    //优化算法,不用再判断Z,已知x,y就可以求到z,且此时可以减少if中的判断
    /*
    int x,y,z;
    for(x = 1 ; x<=20;x++)
        for(y = 1 ; y <=33 ; y++)
        {
            z = 100 - x - y;
            if(5*x+y*3+z/3==100)
                {
                  printf("公鸡数量=%d\t",x);
          printf("母鸡数量=%d\t",y);
          printf("雏鸡数量=%d\n",z);
                }
        }
    */

那么就可以总结出枚举的优化其实就是逻辑减少你的无脑for循环

其他算法:

递归:

找出口(什么时候return出口) 总结规律,调用形如f(规律)的函数。

例子1:

hannoi(int n,char a,char b,char c)`

{//所谓出口:n==1是出口//所谓总结规律:/*

​    其他分别是a上的n-1物品借助c挪动到b`

​    最后一个n直接从a到c

​   B上的n-1个物品借助a挪动到c

​    *///真实代码为

    if(n==1)     //定义出口

  {

   move(n,a,c);    //只有一个时,直接将a上的东西挪动到c

  }
  else

  {

 hannoi(n-1,a,c,b);//如果a上不止一个东西,就借助c把前n-1个挪动到b

 move(n,a,c);//然后将最后一个,(此时a上只有一个,c上没有,b上有n-1个)即第n个直接挪动到c

 hannoi(n-1,b,a,c);//此时再把n-1个借助a从b挪到c(递归的思想在这里!!)

  }

}

void move(int n,char x,char y)

{

  printf("move %d from %c to %c\n",n,x,y);

  num++;

}

其他简单例子:

n的阶乘n!

大概是这个样子

int f(int n)

{

if(n==1||n==0) return 1;//所谓出口

return n*f(n-1);//所谓规律

}

其他经典但不很简单的例子

快排

int PartSort(int* pArray, int nLeft, int nRight)    //取键值
{
    int nKey = pArray[nLeft];       //取头
    while (nLeft < nRight)
    {
        while (pArray[nRight] >= nKey && nRight > nLeft)    //最后的元素和头元素比较,即右指针
        {
            nRight--;   //不是,拉回
        }
        pArray[nLeft] = pArray[nRight];//出来
        while (pArray[nLeft] < nKey && nLeft < nRight)      //和头元素比较,即左指针
        {
            nLeft++;
        }
        pArray[nRight] = pArray[nLeft];
    }
    pArray[nLeft] = nKey;
    return nLeft;//找到序列分段的点
}

void QuickSortRecursion(int* pArray, int nLeft, int nRight)
{
	if (NULL == pArray)
	{
		return;
	}
	if (nLeft >= nRight) //两边重合,退出
	{
		return;
	}
    int nMid = PartSort(pArray, nLeft, nRight); //拿到键值
    //int nMid = pArray[(nLeft+nRight)/2]; 错误取法
    QuickSortRecursion(pArray, nLeft, nMid - 1);//键值左边的快排
    QuickSortRecursion(pArray, nMid + 1, nRight);//键值右边的快排
}

其中,快排最经典的还包括取指针的交换

void myswap(int *a,int *b)
{

    int t;
    t=*a;

    *a=*b;

    *b=t;
}

背包算法(dp):

dp算法分为多种,一般是01背包和完全背包,还有其他的变化背包问题

主要理解了01背包其他的…也还是不好理解(其实我只会01问题)

/*
* dp算法最主要的是要确定dp以一位数组还是以二维数组的形式
* dp[i]代表...其实我还不会...这个属于变化背包问题,视情况而定
* dp[i][j]一般代表总共要i个物品,一共有j总时间,能拿到的最大值
*/
/*
* 一般的01背包问题最主要的是初始化边界的问题
* 如:要0个物品,j的时间,那么最终的d[0][j]肯定都是0
* 再如:要i个物品,可是不给时间,那么最终的d[i][0]肯定都是0
* 就像这个鸭子去初始化就好啦 m代表物品个数,t代表时间
for(int i = 0 ; i <= m; i++)
        dp[i][0] = 0;
    for(int i = 0 ; i <= t; i++)
        dp[0][i] = 0;
 */
 //剩下的最主要的问题:就是怎么取的问题
 直接上代码:
 for(int i = 1; i <= m ; i++)		//双重循环遍历整个背包
    {
        for(int j = 1; j <= t;j++)
        {
            if(j<time[i])		//不够时间取当下的物品,只能取前一个
            {
               dp[i][j] = dp[i-1][j];
            printf("dp[%d][%d]=%d\n",i,j,dp[i-1][j]);//打印出来看看...
            }
            else
            {
            	//时间足够,那么就比较前面已经取得的总价值和接下来要取的总价值的大小,取最大
                dp[i][j] = max(dp[i-1][j],dp[i-1][j-time[i]]+price[i]);
                printf("dp[i-1][j-time[i]]=dp[%d][%d]=%d\t",i-1,j-time[i],dp[i-1][j-time[i]]+price[i]);
                printf("dp[%d][%d]=%d\n",i,j,dp[i][j]);
            }

        }
    }
    printf("%d",dp[m][t]);
 

其他的背包问题后续…等俺学会了再回来

迪杰斯特拉(Dijkstra)算法

对于图的算法,一般有Dijkstra算法和Floyd算法。会一个一般就可以了

其实我也只会dijkstra…够用了够用了,灵魂狗头

如果我写的太菜,这个博主写的dijkstra非常的详细

直接上代码

/* 局部代码如下 */
int dijsktra()
{
    memset(dist,0x3f,sizeof dist); //这里的0x3f可以当成无穷大使用
    dist[1] = 0;
    for(int i = 0 ; i < n ; i++)
    {
        int t = -1; //便于更新第一个的值
        for(int j = 1 ; j <= n ; j++)
        {
            if(!vis[j]&&(t==-1||dist[t]>dist[j]))
                t = j;//没进过的点,或者第一个点,或者此时的t>j
        }
        vis[t] = 1;
        for(int j = 1 ; i <= n ; j++)
        {
            //用t来更新其他点到起点的值
            //比较此点和下一结点那个大,取最小
            dist[j] = min(dist[j],dist[t]+g[t][j]);
        }
    }
    if(dist[n]== 0x3f3f3f3f) return -1;
    else return dist[n];
}

供你测试的代码如下:(如果你看得懂我怎么测试的话

#include <bits/stdc++.h>
using namespace std;
const int N = 510;
int g[N][N];
int dist[N];
bool vis[N];
int n,m;
int dijsktra()
{
    memset(dist,0x3f,sizeof dist);
    dist[1] = 0;
    for(int i = 0 ; i < n ; i ++ )
    {
        int t = -1 ;
        for(int j = 1 ; j <= n ; j++)
        {
            if(!vis[j]&&(t==-1||dist[t]>dist[j]))
                t = j;
        }
        vis[t] = 1;
        for(int j = 1 ; j <= n ; j++)
        {
            dist[j] = min(dist[j],dist[t]+g[t][j]);
        }

    }
    if(dist[n] == 0x3f3f3f3f) return -1;
            else return dist[n];
}

int main()
{
    cin>>n>>m;
    memset(g,0x3f,sizeof g);
    for(int i = 0 ; i < m ; i++)
    {
        int x,y,z;
        cin>>x>>y>>z;
        g[x][y] = min(g[x][y],z);
    }
    cout<<dijsktra()<<endl;
    return 0;
}

总结:其实最短路的问题,一般可以用脑神经回路算法解决,即肉眼观察法

那么,。如果你数据量实在不适合脑神经算法或者其他情况呢,或者你该用上dijsktra

这或许不是算法…

在c++中,如果你学会使用API函数后,就是那些STL函数啦,。那么你就会事倍功半事半功倍啦。

最常用的(就是我目前知道的)

如sort函数

sort(a,a+num)
//其中,a是你要传入的数组首地址,num是你这个数组有多少个数据
//你问我有多少个数据有时候不确定怎么办?凉拌???其实。。。。你可以用很多简单的算法或者小技巧就可以得到啦
//实在不行,拿手指头数它!
//那么解释一下,这个num的用处其实是确定你数据量的大小,会自动的选择时间复杂度更小的排序算法。如希尔、快排等

如memset函数

memset(dist,0x3f,sizeof dist);
/* 算法功能,初始化数组值 */
/* 其中,dist就是你要传入的数组,中间的是你要初始化的值 ,最后是你的数组大小*/

如一些查找算法binary_search();

binary_search(a,a+12,5);
/* 
* 其中,a是数组,+12是数组长度,最后的5是你要找的数字 */
* 返回类型:bool型,0为没找到,1为找到
*/

API之lower_bound();函数

lower_bound(a,a+12,10)-a;
/*
* 作用:返回找到的第一个大于等于index_num的下标
* 参数:arr[]数组首地址,arr+数组长度,index_num查找的值
* 你问我为什么要减a?我也不知道.....其实呢,就是减去首地址,返回的才是下标值,就是这么用的,不必纠结
*/
顺便加上另一个差不多的
upper_bound(a,a+12,99)-a;
   /**
    * API之upper_bound();函数
    * 作用:返回找到的第一个大于index_num的下标
    * 参数:arr[]数组首地址,arr+数组长度,index_num查找的值
    */

c_srt()函数

/**
* API之c_str();函数
* 作用:返回一个char* 的指针
* 参数:直接.调用的形式
* 注意:一定要使用strcpy()函数 等来操作方法c_str()返回的指针
*/
    char *cstr;
    string str("Please hello to me");
    cstr = new char [str.size()+1];
    //strcpy(cstr,str.c_str());
    cout<<str.c_str()<<endl;
    return 0;

其实还有好些其他的常用函数

你问我还有哪些?

我好像暂时只记得这些。。。。 其实肯定有很多其他的

/----------------------------------------分割线-------------------------------------------------/
等待后续更新…

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

白面师傅

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

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

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

打赏作者

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

抵扣说明:

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

余额充值