zyl hope实验室第二次总结

​​​​​​2024.1.24、1.25

这两天继续练习了dfs。

DFS

简要来说就是对每一个可能的分支路径深入到不能再深入为止,且不能重复遍历,即每个节点只能遍历一次。

回溯法:

本质就是一种蛮力法,只是通过一定的方法可以使得蛮力法中的一些基本情况可以提前排除从而提高蛮力算法效率,回溯可以理解为排除这些不满足条件的基本情况的过程。

刷了几道题。

填涂颜色 - 洛谷

这道题目就可以用DFS写,大体思路:把外围的 0全部换成3,再把剩下的0换成2,然后把3换回0。首先设起点为(0,0),题目上说的是n>=1,为什么从(0,0)开始呢,因为用dfs是向四周试探,如果外围不加一圈0,就会忽略掉一些外围的0(没于其他0连在一起)如图:

代码如下:


#include<stdio.h>
int a[35][35];
int n;
int f[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
void dfs(int x,int y)
{
    if(a[x][y]!=0)
    {
        return; //不满足条件,回溯
    }
    else
    {
        a[x][y]=3; 
        for(int i=0;i<4;i++)
        {
            int dx=x+f[i][0];
            int dy=y+f[i][1];
            if(dx<0||dy<0||dx>n+1||dy>n+1)
            {
                continue;
            }

              dfs(dx,dy); //递归寻找0
        }
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<=n+1;i++)
    {
        for(int j=0;j<=n+1;j++)
        {
            a[i][j]=0;
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            scanf("%d",&a[i][j]);
        }
    }
   dfs(0,0);  //起始位置
   for(int i=1;i<=n;i++)
   {
       for(int j=1;j<=n;j++)
       {
           if(a[i][j]==0)
           {
               a[i][j]=2;
           }
           if(a[i][j]==3)
           {
               a[i][j]=0;
           }
           printf("%d ",a[i][j]);
       }
       printf("\n");
   }
    return 0;
}

 题目:

[COCI 2008/2009 #2] PERKET - 洛谷

这里用到了回溯法01背包,就像一个2茶树,每个节点都会储存答案,也是当时疑惑的地方,我们可以知道如果加入第一种材料时比加入第二种材料时的差值小,那么我们肯定选单单加第一种材料,但是第一种材料家第三种不一定比第一、2、3种加起来小,为什么就是sum=min(abs(x-y),sum);呢,可知01背包只有两种取和不取,都用dfs搜索,会一直分叉,min也是包括了这两种情况的。

代码如图所示:

#include<stdio.h>
#include<math.h>
int a[20];
int b[20];
int sum=1000000000;
int t;
int min(int x,int y)
{
    if(x>y)
    {
        return y;
    }
    else
    {
        return x;
    }
}
void dfs(int i,int x,int y)
{
    if(i>t)
    {
        if(x==1&&y==0)
        {
            return;
        }

            sum=min(abs(x-y),sum);
            return;

    }
    dfs(i+1,x*a[i],y+b[i]);//递归结束,才会到下一个递归
    dfs(i+1,x,y);
}
int main()
{
    scanf("%d",&t);
    for(int i=1;i<=t;i++)
    {
        scanf("%d %d",&a[i],&b[i]);
    }
    dfs(1,1,0);
    printf("%d\n",sum);
    return 0;
}

题目:

思路:

就是两个相隔时间的耗电量->[(Mi-Mi-1)*a]与关机一次的耗电量->(b)比大小,设sum=0,哪个小那个累加,最后sum跟总电量比大小就可以了

#include<stdio.h>
unsigned long long min(unsigned long long x,unsigned long long y)
{
    if(x<y)
    {
        return x;
    }
    else
    {
        return y;
    }
}
int main()
{
    unsigned long long n,f,a,b;
    int t;
    int arr[200005]={0};
    scanf("%d",&t);
    while(t--)
    {
        unsigned long long sum=0;
        scanf("%llu%llu%llu%llu",&n,&f,&a,&b);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&arr[i]);
        }
        for(int i=1;i<=n;i++)
        {
            unsigned long long ret=min((arr[i]-arr[i-1])*a,b);
            sum+=ret;
        }
        if(sum<f)
        {
            printf("YES\n");
        }
        else
        {
            printf("NO\n");
        }
    }
    return 0;
}

  • 13
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值