c++搜索剪枝常见方法与技巧

news2024/11/26 10:01:51

目录

      

            搜索剪枝常见方法与技巧

关键字  搜索方法,剪枝

摘要

正文

  小结

程序

参考书目


      

            搜索剪枝常见方法与技巧

关键字  搜索方法,剪枝

摘要

搜索是计算机解题中常用的方法,它实质上是枚举法的应用。由于它相当于枚举法,所以其效率是相当地的。因此,为了提高搜索的效率,人们想出了很多剪枝的方法,如分枝定界,启发式搜索等等。在竞赛中,我们不仅要熟练掌握这些方法,而且要因地制宜地运用一些技巧,以提高搜索的效率。

正文

搜索的效率是很低的,即使剪枝再好,也无法弥补其在时间复杂度上的缺陷。因此,在解题中,除非其他任何方法都行不通,才可采用搜索。

既然采用了搜索,剪枝就显得十分的必要,即使就简简单单的设一个槛值,或多加一两条判断,就可对搜索的效率产生惊人的影响。例如N后问题,假如放完皇后再判断,则仅仅只算到7,就开始有停顿,到了8就已经超过了20秒,而如果边放边判断,就算到了10,也没有停顿的感觉。所以,用搜索就一定要剪枝。

剪枝至少有两方面,一是从方法上剪枝,如采用分枝定界,启发式搜索等,适用范围比较广;二是使用一些小技巧,这类方法适用性虽不如第一类,有时甚至只能适用一道题,但也十分有效,并且几乎每道题都存在一些这样那样的剪枝技巧,只是每题有所不同而已。

问题一:(最短编号序列)

表A和表B各含k(k<=20)个元素,元素编号从1到k。两个表中的每个元素都是由0和1组成的字符串。(不是空格)字符串的长度<=20。例如下表的A和B两个表,每个表都含3个元素(k=3)。

    元素编号

     字符串

       1

      1

       2

      10111

       3

      10

表A 表B

    元素编号

     字符串

       1

      111

       2

      10

       3

      0

对于表A和表B,存在一个元素编号的序列2113,分别用表A中的字符串和表B 中的字符串去置换相应的元素编号,可得相同的字符串序列101111110,见下表。

  元素编号序列

    2

    1

    1

    3

  用表A的字符串替换

   10111

    1

    1

    10

  用表B的字符串替换

    10

   111

   111

    0

对表A和表B,具有上述性质的元素编号序列称之为S(AB)。对于上例S(AB)=2113。

编写程序:从文件中读入表A和表B的各个元素,寻找一个长度最短的具有上述性质的元素编号序列S(AB)。(若找不到长度<=100的编号序列,则输出“No Answer”。

对于这道题,因为表A和表B不确定,所以不可能找到一种数学的方法。因为所求的是最优解,而深度优先搜索很容易进入一条死胡同而浪费时间,所以必须采用广度优先搜索的方法。但是,广度优先搜索也有其缺陷。当表A和表B中的元素过多是,扩展的结点也是相当多的,搜索所耗费的时间也无法达到测试的要求。为了解决这个问题,就必须对搜索的算法加以改进。分枝限界似乎不行,因为无法确定代价。而且,由于目标不确定,也无法设定估价函数。但是,因为此题的规则既可以正向使用,又可以逆向使用,于是便可以采用双向搜索。

在大方法确定后,算法的框架就已经基本形成,但即使如此,算法也还有可改进的地方。

  1. 存储当前的A串和B串是很费空间的,但因为A串和B串的大部分相同,故只需记录不同部分,并作个标记。再换成动态存储。
  2. 为了保证两个方向扩展结点的速度相对平衡,可以采取每次扩展结点数较少的方向,而不是两方向轮流扩展。

如此一来,搜索的效率就比单纯的广度优先搜索有了明显的提高。

(附程序sab.pas)

有时,搜索也会有不同的搜索方法(如多处理机调度问题),也会产生不同的效率。

问题二:(任务安排)

N个城市,若干城市间有道路相连,一辆汽车在城市间运送货物,总是从城市1出发,又回到城市1。该车每次需完成若干个任务,每个任务都是要求该车将货物从一个城市运送至另一个。例如若要完成任务2->6,则该车一次旅程中必含有一条子路径。先到2,再到6。

如下图所示,如果要求的任务是2->3,2->4,3->1,2->5,6->4,则一条完成全部任务的路径是1->2->3->1->2->5->6->4->1。

 4

1   2    6

  5

  3 7

    编程由文件读入道路分布的领接矩阵,然后对要求完成的若干任务,寻找一条旅行路线,使得在完成任务最多的前提下,经过的城市总次数最少。如上例中经过城市总次数为8,城市1和2各经过2次均以2次计(起点不计),N<60。

这道题,因为很难找到数学规律,便只有采用搜索的方法。

首先,第一感觉便是:从城市i出发,便搜索所有相邻的城市,再根据当前所处的城市,确定任务的完成情况,从中找到最优解。这种搜索的效率是极低的,其最大原因就在于:目标不明确。

根据题意,我们只需到达需上货和下货的城市,其它的城市仅作为中间过程,而不应作为目标。因此,首先必须确定可能和不可能完成的任务,然后求出任意两城市间的最短路径。在搜索时,就只需考虑有货要上的城市,或者是要运到该城市的货全在车上,其它不须考虑。同时,还可以设定两个简单的槛值。如果当前费用+还需达的城市>=当前最优解,或当前费用+返回城市1的费用>=当前最优解,则不需继续往下搜索。

这种方法与第一感的方法有天壤之别。(附程序travell.pas)

问题三:(多处理机调度问题)

设定有若干台相同的处理机P1,P2      Pn,和m个独立的作业J1,J2      jm,处理机以互不相关的方式处理作业,现约定任何作业可以在任何一台处理机上运行,但未完工之前不允许中断作业,作业也不能拆分成更小的作业,已知作业Ji需要处理机处理的时间为Ti(i=1,2      m)。编程完成以下两个任务:

任务一:假设有n台处理机和m个作业及其每一个作业所需处理的时间Ti存放在文件中,求解一个最佳调度方案,使得完成这m个作业的总工时最少并输出最少工时。

任务二:假设给定作业时间表和限定完工时间T于文件中,求解在限定时间T内完成这批作业所需要最少处理机台数和调度方案。

此题有两种搜索方法:

方法一:按顺序搜索每个作业。当搜索一个作业时,将其放在每台处理机搜索一次。

方法二:按顺序搜索每台处理机。当搜索一台处理机时,将每个作业放在上面搜索一次。

对比上述两种方法,可以发现:方法二较方法一更容易剪枝。

下面是两中方法剪枝的对照:

对于方法一:只能根据目前已确定的需时最长的处理机的耗时与目前最佳解比较。

对于方法二:可约定Time[1]>Time[2]>Time[3]>       >Time[n](Time[i]表示第i台处理机的处理时间),从而可以设定槛值:如当前处理机的处理时间>=目前最佳解,或剩下的处理机台数×上一台处理机的处理时间<剩余的作业需要的处理时间,则回溯。因为在前面的约束条件下,已经不可能有解。

    因此,从上面的比较来看,第二种方法显然是比第一种要好的。下面就针对第二种方法更深一层的进行探讨。

   对于任务一,首先可以用贪心求出Time[1]的上界。然后,还可以Time[1]的下界,UP(作业总时间/处理机台数)。(UP表示大于等于该小数的最小整数)。搜索便从上界开始,找到一个解后,若等于下界即可停止搜索。

(附程序jobs_1.pas)

    对于任务二,可采用深度+可变下界。下界为:UP(作业总时间/限定时间),即至少需要的处理机台数。并设定Time[1]的上界为T。

(附程序jobs_2.pas)

  小结

搜索的使用相当广泛,几乎每题都可以采用搜索的方法。虽然如此,搜索也切不可滥用。只有当问题无规律可寻时,才可用搜索。一旦确定了使用搜索,就一定要想办法对其进行剪枝。无论是采用剪枝的常见方法,还是用一些搜索的小技巧,虽都无法降低搜索的时间复杂度,却总还是大有裨益的。

程序

1. 最短编号序列:sab.pas

program sab;

type aa=string[100];

     ltype=record

                 f:integer;  {父指针}

                 k,d,la,lb:shortint;

   {k--剩余串标志,d--序列中元素的编号,la,lb--A,B两串的串长}

                 st:^aa;  {剩余串}

     end;

const maxn=1300;

var t,h:array[0..1] of integer;  {h--队首指针,t--队尾指针,0表示正向,1表示逆向}

    p:array[0..1,1..maxn] of ltype;  {p[0]--正向搜索表,p[1]--逆向搜索表}

    strs:array[1..2,1..20] of string[20];  {strs[1]--表A元素,strs[2]--表B元素}

    n:integer;   {表A和表B的元素个数}

procedure readp;  {读入数据}

var f:text;

    st:string;

    i,j:integer;

begin

     write('File name:');

     readln(st);

     assign(f,st);

     reset(f);

     readln(f,n);

     for i:=1 to n do

         readln(f,strs[1,i]);

     for i:=1 to n do

         readln(f,strs[2,i]);

     close(f);

end;

procedure print(q,k:integer);  {从k出发,输出沿q方向搜索的元素编号}

begin

     if k<>1 then begin

        if q=1 then

           writeln(p[q,k].d);

        print(q,p[q,k].f);

        if q=0 then

           writeln(p[q,k].d);

     end;

end;

procedure check(q:shortint);  {判断两方向是否重合,q表示刚产生结点的方向的相反方向}

var i:integer;

begin

     for i:=1 to t[1-q]-1 do

         if (p[q,t[q]].k<>p[1-q,i].k) and (p[q,t[q]].st^=p[1-q,i].st^) and

            (p[q,t[q]].la+p[1-q,i].la<=100) and (p[q,t[q]].lb+p[1-q,i].lb<=100)

            then begin

                      if q=0 then

                         begin

                              print(0,t[q]);

                              print(1,i);

                         end

                      else begin

                                print(0,i);

                                print(1,t[q]);

                           end;

                      halt;

            end;

end;

procedure find(q:shortint); {沿q方向扩展一层结点}

var i:integer;

    sa,sb:aa;

begin

     for i:=1 to n do

         if (p[q,h[q]].la+length(strs[1,i])<=100) and

            (p[q,h[q]].lb+length(strs[2,i])<=100) then

            begin

                 sa:='';sb:='';

                 if p[q,h[q]].k=1

                    then sa:=p[q,h[q]].st^

                    else sb:=p[q,h[q]].st^;

                 if q=0 then  {沿不同方向将编号为i的元素加到序列中}

                    begin

                         sa:=sa+strs[1,i];

                         sb:=sb+strs[2,i];

                         while (sa<>'') and (sb<>'') and (sa[1]=sb[1]) do

                               begin

                                    delete(sa,1,1);

                                    delete(sb,1,1);

                               end

                    end

                 else begin

                           sa:=strs[1,i]+sa;sb:=strs[2,i]+sb;

                           while (sa<>'') and (sb<>'') and

                                 (sa[length(sa)]=sb[length(sb)]) do

                                 begin

                                      delete(sa,length(sa),1);

                                      delete(sb,length(sb),1);

                                 end;

                      end;

                 if (sa='') or (sb='') then  {生成一个新的结点}

                    with p[q,t[q]] do

                         begin

                              f:=h[q];d:=i;

                              la:=p[q,h[q]].la+length(strs[1,i]);

                              lb:=p[q,h[q]].lb+length(strs[2,i]);

                              new(st);

                              if sa='' then

                                 begin

                                      k:=2;st^:=sb

                                 end

                              else begin

                                        k:=1;st^:=sa;

                                   end;

                              check(q);

                              inc(t[q]);

                         end;

            end;

     inc(h[q]);

end;

begin

     readp;

     h[0]:=1;h[1]:=1;

     t[0]:=2;t[1]:=2;

     new(p[0,1].st);p[0,1].st^:='';

     new(p[1,1].st);p[1,1].st^:='';

     {队列初始化}

     while (h[0]<t[0]) and (h[1]<t[1]) and (t[0]<maxn) and (t[1]<maxn) do

           if t[0]<t[1]  {比较两方向的节点数,向结点数少的方向扩展}

              then find(0)

              else find(1);

     writeln('No answer!');

end.

  1. 任务安排:travell.pas

program travell;

var path,  {path[i,j]--以i为起点第j个运输终点}

    next,  {next[i,j]--从i到j的最短路径中,i顶点的下一个顶点}

    dist,  {dist[i,j]--从i到j的最短路径长度}

    road:array[1..60,1..60] of integer;  {道路的邻接矩阵}

    head,  {head[i]--以i为起点的任务数}

tail,  {tail[i]--0表示以i为终点无任务或已完成}

   {1表示以i为终点的任务的所有顶点都在完成任务路径中}

   {k+1表示以i为终点的所有任务,还有k个顶点未到达}

    arrive:array[1..60] of integer;  {arrive[i]--顶点i的经过次数}

    d,  {完成任务路径}

    bestd:array[1..100] of integer;  {当前最佳完成任务路径}

    left,  {必经结点个数}

    cost,  {当前代价}

    mincost,  {最佳完成任务代价}

    s,  {经过顶点数}

    bests,  {最佳完成任务所经过的顶点数}

    m,  {任务数}

    n:integer;  {城市数}

procedure findshortest;  {求任意两点间的最短路径}

var i,j,k:integer;

begin

     for i:=1 to n do

         for j:=1 to n do

             if road[i,j]=1 then

                begin

                     dist[i,j]:=1;

                     next[i,j]:=j

                end

             else dist[i,j]:=100;

     for k:=1 to n do

         for i:=1 to n do

             for j:=1 to n do

                 if dist[i,k]+dist[k,j]<dist[i,j] then

                    begin

                         dist[i,j]:=dist[i,k]+dist[k,j];

                         next[i,j]:=next[i,k];

                    end;

end;

procedure init;  {读入数据并初始化数据}

var i,j,k:integer;

    st:string;

    f:text;

begin

     write('File name:');

     readln(st);

     assign(f,st);

     reset(f);

     readln(f,n);

     for i:=1 to n do

         for j:=1 to n do

             read(f,road[i,j]);

     findshortest;

     readln(f,m);

     for i:=1 to m do

         begin

              read(f,j,k);

              if (dist[1,j]<100) and (dist[1,k]<100) then

                 begin

                      inc(head[j]);

                      inc(tail[k]);

                      path[j,head[j]]:=k;

                 end;

         end;

     close(f);

     for i:=1 to m do

         if tail[i]>0 then

            inc(tail[i]);

     for i:=1 to head[1] do

         dec(tail[path[1,i]]);

     head[1]:=0;inc(s);d[s]:=1;left:=0;

     cost:=0;mincost:=maxint;

     for i:=2 to n do

         if (head[i]>0) or (tail[i]>0) then

            inc(left);

end;

procedure try;  {搜索过程}

var i,j,k:integer;

    p:boolean;

begin

     if (cost+left>=mincost) or (cost+dist[1,d[s]]>=mincost) then exit;

     if left=0 then  {是否完成了所有任务}

        begin

             mincost:=cost+dist[1,d[s]];

             bestd:=d;

             bests:=s;

             inc(bests);bestd[bests]:=1;

             exit;

        end;

     for i:=2 to n do

         if (head[i]>0) or (tail[i]=1) then  {如果去i顶点有必要}

            begin

                 inc(cost,dist[d[s],i]);

                 inc(arrive[i]);

                 inc(s);

                 d[s]:=i;

                 if arrive[i]=1 then  

{如果i顶点第一次到达,则所有以i为起点的任务的终点tail值减1}

                    for j:=1 to head[i] do

                        dec(tail[path[i,j]]);

                 k:=head[i];

                 head[i]:=0;

                 if tail[i]=1 then  

 {如果完成了以i为终点的所有任务,该点则不需再经过}

                    begin

                         p:=true;

                         dec(tail[i]);

                    end

                    else p:=false;

                 if tail[i]=0 then  

                    dec(left);

                 try;

   {恢复递归前的数据}

                 if tail[i]=0 then

                    inc(left);

                 if true then

                    inc(tail[i]);

                 head[i]:=k;

                 if arrive[i]=1 then

                    for j:=1 to head[i] do

                        inc(tail[path[i,j]]);

                 dec(s);

                 dec(arrive[i]);

                 dec(cost,dist[d[s],i]);

         end;

end;

procedure show(i,j:integer);  {输出从i到j的最短路径}  

begin

     while i<>j do begin

           write('-->',next[i,j]);i:=next[i,j];

     end;

end;

procedure print;  {输出最佳任务安排方案}

var i:integer;

begin

     write(1);

     for i:=1 to bests-1 do

         show(bestd[i],bestd[i+1]);

     writeln;

     writeln('Min cost=',mincost);

end;

begin

     init;

     try;

     print;

end.

  1. 多处理机调度问题:

任务一:jobs_1.pas

program jobs_1;

const maxn=100;  {处理机的最多数目}

      maxm=100;  {作业的最多数目}

var

   t:array[1..maxm] of timeint;   {t[i]--处理作业i需要的时间}

   time,        {time[i]--第i台处理机的处理时间}

   l, {l[i]--第i台处理机处理作业的数目}

   l1:array[0..maxn] of timeint; {l1[i]--目前最优解中第i台处理机处理作业的数目}

   a, {a[i,j]--第i台处理机处理的第j个作业耗费的时间}

   a1:array[1..maxn,1..maxm] of integer;

   {a1[i,j]--目前最优解中第i台处理机处理的第j个作业耗费的时间}

   done:array[1..maxm] of boolean; {done[i]--true表示作业i已完成,false表示未完成}

   least, {处理时间的下界}

   i,j,k,n,m,

   min, {目前最优解的处理时间}

   rest:integer; {剩余作业的总时间}

procedure print;  {输出最优解}

var i,j:integer;

begin

     for i:=1 to n do

         begin

              write(i,':');

              for j:=1 to l1[i] do

                  write(a1[i,j]:4);

              writeln;

         end;

     writeln('T0=',time[0]+1);

end;

procedure readp;  {读入数据}

var

   f:text;

   st:string;

   i,j,k:integer;

begin

     write('File name:');readln(st);

     assign(f,st);reset(f);

     readln(f,n,m);

     for i:=1 to m do

  begin

          read(f,t[i]);inc(rest,t[i]);

         end;

     close(f);

     least:=(rest-1) div n+1;  {定下界}

     for i:=1 to m-1 do  {排序}

         for j:=i+1 to m do

             if t[j]>t[i] then

                begin k:=t[i];t[i]:=t[j];t[j]:=k end;

end;

procedure try(p,q:integer);  {从p--m中选取作业放到处理机q上}

var j:integer;

    z:boolean;

begin

     

     z:=true;

     for j:=p to m do

         if not done[j] and (time[q]+t[j]<=time[q-1]) then  {选择合适的作业}

            begin

                 z:=false;done[j]:=true;

                 inc(l[q]);a[q,l[q]]:=t[j];inc(time[q],t[j]);dec(rest,t[j]);

                 try(j+1,q);

                 dec(l[q]);dec(time[q],t[j]);inc(rest,t[j]);done[j]:=false;

   if time[1]>time[0] then exit;

   {找到解后退回处理机1,需更新time[1],使之减小到time[0]}

   {2--n台处理机就不需再搜索}

            end;

     if z and ((n-q)*time[q]>=rest) then  {如果处理机q已无法放任何作业}

        if rest=0 then  {找到一组解}

           begin

                a1:=a;l1:=l;

                time[0]:=time[1]-1;

                if time[1]=least then

                   begin print;halt end;

           end

        else if q<n then  {继续搜索}

                try(1,q+1);

end;

begin

     readp;

     fillchar(time,sizeof(time),0);

     fillchar(a,sizeof(a),0);

     fillchar(l1,sizeof(l1),0);

     fillchar(l,sizeof(l),0);

     for i:=1 to m do  {贪心求上界}

         begin

              k:=1;

              for j:=2 to n do

                  if time[j]<time[k] then k:=j;

              time[k]:=time[k]+t[i];

              l1[k]:=l1[k]+1;

              a1[k,l1[k]]:=t[i];

         end;

     min:=time[1];time[0]:=min-1;

     for i:=2 to n do

         if time[i]>min then min:=time[i];

     if min=least then  {如上下界相等}

        begin

             print;

             halt;

        end;

     fillchar(time,sizeof(time),0);

     time[0]:=min-1;  {将上界减1,以找到更优的解}

     try(1,1);

     print;

end.

 任务二:jobs_2.pas

program jobs_2;

const maxn=100;  {处理机的最多数目}

      maxm=100;  {作业的最多数目}

var

   t:array[1..maxm] of timeint;   {t[i]--处理作业i需要的时间}

   time,        {time[i]--第i台处理机的处理时间}

   l, {l[i]--第i台处理机处理作业的数目}

   l1:array[0..maxn] of timeint; {l1[i]--目前最优解中第i台处理机处理作业的数目}

   a, {a[i,j]--第i台处理机处理的第j个作业耗费的时间}

   a1:array[1..maxn,1..maxm] of integer;

   {a1[i,j]--目前最优解中第i台处理机处理的第j个作业耗费的时间}

   done:array[1..maxm] of boolean; {done[i]--true表示作业i已完成,false表示未完成}

   least, {处理时间的下界}

   i,j,k,tmax,m,

   min, {目前最优解的处理时间}

   rest:integer; {剩余作业的总时间}

procedure print;  {输出最优解}

var i,j:integer;

begin

     for i:=1 to least do

         begin

              write(i,':');

              for j:=1 to l1[i] do

                  write(a1[i,j]:4);

              writeln;

         end;

     writeln('Min=',least);

end;

procedure readp;  {读入数据}

var

   f:text;

   st:string;

   i,j,k:integer;

begin

     write('File name:');readln(st);

     assign(f,st);reset(f);

     readln(f,tmax,m);

     for i:=1 to m do begin

         read(f,t[i]);inc(rest,t[i]);

     end;

     close(f);

     least:=(rest-1) div tmax+1;  {确定下界}

     for i:=1 to m-1 do  {排序}

         for j:=i+1 to m do

             if t[j]>t[i] then

                begin k:=t[i];t[i]:=t[j];t[j]:=k end;

end;

procedure try(p,q:integer); {从p--m中选取作业放到处理机q上}

var j:integer;

    z:boolean;

begin

     z:=true;

     for j:=p to m do

         if not done[j] and (time[q]+t[j]<=time[q-1]) then  {找到合适的作业}

            begin

                 z:=false;done[j]:=true;

                 inc(l[q]);a[q,l[q]]:=t[j];inc(time[q],t[j]);dec(rest,t[j]);

                 try(j+1,q);

                 dec(l[q]);dec(time[q],t[j]);inc(rest,t[j]);done[j]:=false;

            end;

     if z and ((least-q)*time[q]>=rest) then  {如果处理机q已无法放任何作业}

        if rest=0 then  {找到最优解}

           begin

                a1:=a;l1:=l;

              print;halt

           end

        else if q<min then  {继续搜索}

                try(1,q+1);

end;

begin

     readp;

     for i:=1 to m do  {判断无解情况,即某一任务所需时间超过规定时间}

         if t[i]>tmax then

            begin writeln('No answer!');exit end;

     repeat

           fillchar(time,sizeof(time),0);

           fillchar(l,sizeof(l),0);

           fillchar(l1,sizeof(l1),0);

           for i:=1 to m do  {贪心求上界}

               begin

                    k:=1;

                    for j:=2 to least do

                        if time[j]<time[k] then k:=j;

                    time[k]:=time[k]+t[i];

                    l1[k]:=l1[k]+1;

                    a1[k,l1[k]]:=t[i];

               end;

           min:=time[1];

           for i:=2 to least do

               if time[i]>min then min:=time[i];

           if min=least then  {如果贪心得出了最优解}

              begin

                   print;halt;

              end;

           fillchar(time,sizeof(time),0);

           time[0]:=tmax;

           try(1,1);

           inc(least);  {下界加一}

     until least>m;

     print;

end.

参考书目

  1. 《国际国内青少年信息学(计算机)奥林匹克竞赛试题解析(1994-1995》,吴文虎,王建德主编,清华大学出版社。
  2. 《奥林匹克计算机(信息学)入门》,江文哉主编,上海交通大学出版社。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/953043.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

冠达管理 :主升浪前最后一次洗盘?

随着科技的不断发展&#xff0c;人们关于金融商场的了解也越来越深入。在股市中&#xff0c;洗盘是一个非常重要的概念。洗盘是指许多的股票被清洗出某个价位上的持有者&#xff0c;从而拉低该价位上的股票价格&#xff0c;为后续上涨做出铺垫。而在股市中&#xff0c;主升浪前…

DolphinDB 携手白鲸开源 WhaleStudio 打造高效敏捷的 DataOps 解决方案

浙江智臾科技有限公司&#xff08;简称&#xff1a;DolphinDB&#xff09;和北京白鲸开源科技有限公司&#xff08;简称&#xff1a;白鲸开源&#xff09;是在大数据技术领域活跃的两支专业团队。 DolphinDB 专注于为用户提供集高性能存储、复杂分析能力和流处理于一体的实时计…

SUB-1G无线收发芯片DP4306低功耗的单片集成收发机

概述 DP4306是一款高性能低功耗的单片集成收发机&#xff0c;工作频率可覆盖200MHz~ 1000MHz, 芯片集成了射频接收器、射频发射器、频率综合器、GFSK调制器、GFSK 解调器等功能模块。通过SPI接口可以对输出功率、频道选择以及数据包格式进行灵活配置&#xff0c;并且内置CRC、…

如何为新产品做好全网口碑推广?

互联网时代下&#xff0c;产品上市后的口碑营销直接关系到产品的销售量。不管是网购还是线下购物&#xff0c;消费者喜欢通过互联网去查询产品的网络口碑&#xff0c;如果产品评价不好可能不断丢失客户。新产品推出之后做好全网口碑推广&#xff0c;为新品的销售做好铺垫已经成…

MySQL 8 数据清洗总结

MySQL 8 数据清洗三要素&#xff1a; 库表拷贝和数据备份数据清洗SQL数据清洗必杀技-存储过程 前提&#xff1a;数据库关联库表初始化和基础数据初始化&#xff1a; -- usc.t_project definitionCREATE TABLE t_project (id varchar(64) NOT NULL COMMENT 主键,tid varchar(…

Scrum Master 面试问题- ChatGPT 版

之前&#xff0c;我测试了 ChatGPT 如何回答《Scrum Master 面试指南》中的问题&#xff1b;见下文。早在2023 年 1 月&#xff0c;我就不会在 Scrum Master 面试过程中采取下一步&#xff0c;邀请ChatGPT与几名Scrum团队成员进行全方位的面试。 那么&#xff0c;如果 GPT 3.5…

JavaScript(函数,作用域和闭包)

目录 一&#xff0c;什么是函数1.1&#xff0c;常用系统函数1.2&#xff0c;函数声明 1.3&#xff0c;函数表达式二&#xff0c;预解析2.1&#xff0c;函数自调用 2.2&#xff0c;回调函数三&#xff0c;变量的作用域3.1&#xff0c;隐式全局变量 四&#xff0c;作用域与块级作…

如何从0跑起Vue3项目(Node和npm环境配置)

文章目录 vue项目运行Node安装打开vue项目 vue项目 拥有了一个vue3项目后怎么将它跑起来&#xff1f; 期末在学长敲代码那儿做的vue课设&#xff0c;怎么将他从0跑起来&#xff1f; char[] str "如果需要做课设的小伙伴&#xff0c;也可以百度:学长敲代码" strin…

el-switch组件在分页情况下的使用

1.需求: 系统使用者在点击发布状态的开关后,可以对应的发布或者取消发布试卷 2.前端代码: html代码(这里不贴其他表单项的代码了,直接贴el-Switch组件的代码): <!-- qwy: 使用Switch组件,设置发布状态,业务逻辑:在页面初始渲染的时候应该查询发布状态,以根据状…

windows环境装MailHog

背景&#xff1a;win10系统&#xff0c;windows 宝塔&#xff0c;laravel 项目&#xff0c;邮件相关需要装一个MailHog 下载地址&#xff1a;https://sourceforge.net/projects/mailhog.mirror/ 直接下载&#xff0c;下载后双击运行就可以了&#xff0c;系统可能提示”不信任“…

用Socket实现网络通信

文章目录 背景网络编程网络编程三要素 2.Socket之UDP通信程序2.1 UDP发送数据2.2UDP接收数据 3. Socket之TCP通信程序3.1TCP发送数据3.2TCP接收数据 背景 网络编程 ● 计算机网络 是指将地理位置不同的具有独立功能的多台计算机及其外部设备&#xff0c;通过通信线路连接起来…

Linux文件管理知识:查找文件(第二篇)

上篇文章详细介绍了linux系统中查找文件的工具或者命令程序locate和find命令的基本操作。那么&#xff0c;今天这篇文章紧接着查找文件相关操作内容介绍。 Find命令所属操作列表中的条目&#xff0c;有助于我们想要的结果输出。上篇文章已讲到find 命令是基于搜索结果来执行操作…

VScode 调试python程序,debug状态闪断问题的解决方法

0. Few words 之前一直在VSCode中debug C和Python的程序没出过闪断的问题&#xff0c;但是最近在另一台电脑上debug&#xff0c;同样的方法&#xff0c;设置launch.json和CMakeList加debug状态等等操作&#xff0c;如我另一篇blog写的一样&#xff0c;可以点这里查看。 但是&a…

HarmonyOS—UI开发性能提升的推荐方法

注&#xff1a;本文转载自HarmonyOS官网文档 开发者若使用低性能的代码实现功能场景可能不会影响应用的正常运行&#xff0c;但却会对应用的性能造成负面影响。本章节列举出了一些可提升性能的场景供开发者参考&#xff0c;以避免应用实现上带来的性能劣化。 使用数据懒加载 开…

RT-Thread概述与体验

RTT目录结构 最核心的文件只有5个&#xff1a; src\thread.c&#xff1a;线程相关的文件&#xff0c;比如创建线程、启动线程。src\timer.c&#xff1a;定时器相关的文件。src\scheduler.c&#xff1a;调度器&#xff1a;维护线程的就绪链表、提供临界区的进出函数。src\ipc.c…

CRM系统有哪些类型?如何管理客户关系?

什么是是客户关系管理 Zoho CRM是一种经营策略帮助企业建立客户为中心的企业管理模式同时CRM也是一种技术手段帮助企业建立牢靠的客户关系&#xff0c;实现降本增效的目的。例如建立全渠道沟通&#xff0c;提高客户满意度&#xff0c;跟进客户细分开展个性化的营销活动提高市场…

uniapp--- 微信小程序 用户隐私新规相关代码调整【vue3+ts+uView框架】

uniapp— 微信小程序 用户隐私新规相关代码调整【vue3tsuView框架】 官方公告地址&#xff1a;https://developers.weixin.qq.com/community/develop/doc/00042e3ef54940ce8520e38db61801 用户隐私保护指引填写说明地址&#xff1a;https://developers.weixin.qq.com/miniprogr…

C++信息学奥赛1177:奇数单增序列

#include<bits/stdc.h> using namespace std; int main(){int n;cin>>n; // 输入整数 n&#xff0c;表示数组的大小int arr[n]; // 创建大小为 n 的整型数组for(int i0;i<n;i) cin>>arr[i]; // 输入数组元素for(int i0;i<n;i){ // 对数组进行冒泡排序f…

Resource Hacker下载

下载路径 Resource Hacker (angusj.com)http://www.angusj.com/resourcehacker/#download 应用方法示例 【2023年更新】手把手教你去除 WinRAR 的弹窗广告_winrar广告怎么去除_areosun的博客-CSDN博客https://blog.csdn.net/haiyunzhiqiu/article/details/119176038#comment…

管理类联考——逻辑——形式逻辑——汇总篇——知识点突破——性质模态

性质&模态 角度一 角度二 矛盾关系 【对象】(1)所有、有的不;(2)所有不、有的;(3)某个、某个不。 【典例】①所有偶像都是靠颜值的。 ②有的偶像不是靠颜值的。 试分析: (1)如果①为真,试判断②的真假。 (2)如果①为假,试判断②的真假。 (3)①和②是否可…