Kevin的算法笔记(5)搜索①

1.TJU作业题:Lake Counting

如果我们把整个草地看成一个图,那么我们要做的就是深度优先搜索每个点旁边的八个点(如果它是w),每次统计一整块草坪,同时计数器+1。

示例代码如下:

查看代码

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>

using namespace std;

char s[100+3][100+3];
int n,m,ans;

const int tx[8]={-1,-1,-1,0,0,1,1,1};
const int ty[8]={-1,0,1,-1,1,-1,0,1};

void find(int x,int y)
{
    if (x < 1 || x > n || y < 1 || y > m) return; 
    if (s[x][y] != 'W') return;    
    s[x][y]='.';                    
    for (int i=0;i<8;i++) 
        find(x + tx[i], y + ty[i]);
}

int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
        scanf("%s",s[i]+1);
    
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
        if (s[i][j]=='W')          
        {
            find(i,j);
            ans++;
        }
    printf("%d",ans);
}

2. POJ 1011-Sticks

这是一道很经典的剪枝问题,如果暴力枚举,复杂度为o(2^n),一定会超时。

在BFS的基础上考虑如下方面:

①可行的长度一定是总长度S的约数

②如果已经用较大的木棍拼成一根,后续发现不可行,可直接剪枝

③如果有一根木棍比L都大,可直接剪枝

④从大木棍往小木棍搜索,更容易暴露问题

这样我们只要解决很少的几种情况即可。

参考代码如下:

查看代码
 #include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

int n,a[70],vis[70],ans;

bool cmp(int x,int y){
    return x>y;
}

bool dfs(int len,int rest,int pos,int num){
    if(!rest&&!num){
        ans=len;
        return true;
    }
    if(!rest){
        rest=len;
        for(int i=0;i<n;++i){
            if(vis[i]) continue;
            vis[i]=1;
            if(dfs(len,rest-a[i],i+1,num-1))
                return true;
            vis[i]=0;
            return false;
        }
    }
    for(int i=pos;i<n;++i){
        if(vis[i]) continue;
        if(a[i]<=rest){
            vis[i]=1;
            if(dfs(len,rest-a[i],i+1,num-1))
                return true;
            vis[i]=0;
            if(a[i]==rest) break;
            while(a[i+1]==a[i]) ++i;
        }
    }
    return false;
}

int main(){
    while(scanf("%d",&n),n){
        int sum=0,flag=0;
        for(int i=0;i<n;++i){
            scanf("%d",&a[i]);
            sum+=a[i];
        }
        sort(a,a+n,cmp);
        memset(vis,0,sizeof(vis));
        for(int i=a[0];i<=sum/2;++i){
            if(sum%i==0){
                if(dfs(i,i,0,n)){
                    flag=1;
                    break;
                }
            }
        }
        if(flag)
            printf("%d\n",ans);
        else
            printf("%d\n",sum);
    }
    return 0;
}

对于BFS,为了减少搜索步骤,可以使用A*算法,而对于DFS,我们可以用迭代加深算法(IDDFS)来剪枝。另外,对两者结合,迭代加深是迭代次数超过一定值就不再加深,而IDA*算法中,在某个迭代后,步数+估价函数的值超过一定大小就不再剪枝。

posted @ 2026-05-20 21:18  KevinXsll  阅读(7)  评论(0)    收藏  举报