总结第九周

本周结束了搜索题单,开始刷数学的三个题单和二分题单,预计14周前结束。


深搜关于地图问题:
1.注意边界。(注意使用memset的时候要考虑清楚,可能把不需要的部分也进行初始化,影响搜索)。2.不同题目的区别点在于搜索中if语句的不同,根据题意进行编写,也不是很复杂。
3.终止条件:满足便进行return返回,可能是求方案数,也可能是到达最少需要步数一类问题。
(进行回溯,将走过的点在标记为初始化状态,方便下一层循环)

模板题:P1605 迷宫

#include <bits/stdc++.h>
using namespace std;
int n,m,t,sx,sy,fx,fy,ans;
int mp[10][10],vis[10][10];
int dx[5]={0,0,1,-1};
int dy[5]={1,-1,0,0};
void dfs(int x,int y)
{
    if(x==fx&&y==fy)
    {
        ans++;
        return;
    }
    for(int i=0;i<4;i++)
    {
        if(vis[x+dx[i]][y+dy[i]]==0&&mp[x+dx[i]][y+dy[i]]==1)
        {
            vis[x][y]=1;
            dfs(x+dx[i],y+dy[i]);
            vis[x][y]=0;
        }
    }
}
int main()
{
    cin>>n>>m>>t;
    cin>>sx>>sy>>fx>>fy;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        mp[i][j]=1;
    for(int i=1;i<=t;i++)
    {
        int l,r;
        cin>>l>>r;
        mp[l][r]=0;
    }
    dfs(sx,sy);
    cout<<ans<<endl;
    return 0;
}

P1019 [NOIP2000 提高组] 单词接龙
题目要求:
1.求出可拼接长度最大的字符串。
2.一个单词最多可使用2次。
3.存在包含关系的字符串无法拼接。
思路整理:
1.因为规定了“龙”的开头,因此长度从1开始累积。
2.写一个函数返回两个字符串重叠部分的数目。
3.dfs进行遍历,对每个字符串都要考虑两次的情况。

获得重复两个字符串收尾重复元素的方法:

int rp(string s1,string s2)
{
    for(int i=1;i<min(s1.length(),s2.length());i++)
    {
        bool f=1;
        for(int j=0;j<i;j++)
        {
            if(s1[s1.length()-i+j]!=s2[j]) f=0;
        }
        if(f) return i;
    }
    return 0;
}
#include <bits/stdc++.h>
using namespace std;
int n,lg,num[30];
string st[30];
int rp(string s1,string s2)
{
    for(int i=1;i<min(s1.length(),s2.length());i++)
    {
        bool f=1;
        for(int j=0;j<i;j++)
        {
            if(s1[s1.length()-i+j]!=s2[j]) f=0;
        }
        if(f) return i;
    }
    return 0;
}
void dfs(string s,int lg1)
{
    lg=max(lg,lg1);
    for(int i=0;i<n;i++)
    {
        if(num[i]>=2) continue;
        int tmp=rp(s,st[i]);
        if(tmp>0)
        {
            num[i]++;
            dfs(st[i],lg1+st[i].length()-tmp);
            num[i]--;
        }
    }
}
int main()
{
    cin>>n;
    for(int i=0;i<=n;i++)
        cin>>st[i];
    dfs(' '+st[n],1);
    cout<<lg<<endl;
    return 0;
}

P1101 单词方阵

可能是边界问题,最后一组数据总回报re。但加上边界,其他都能过,最后一组数据就wr了,应该是代码的一些细节问题,但就是找不出来。。。。。

#include <bits/stdc++.h>

using namespace std;
int n,d,s[105][105],c[105][2];
bool vis[105][105];
char ch[105][105];
string s1=" yizhong";
int dx[9]={0,0,0,-1,-1,-1,1,1,1};
int dy[9]={0,1,-1,0,-1,1,0,-1,1};
int dfs(int i,int j,int x,int y,int m)
{
    if(m>7)
    {
        vis[i][j]=1;
        return 1;
    }
    if(ch[i+x][j+y]==s1[m])
    {
        if(dfs(i+x,j+y,x,y,m+1))
        {
            vis[i][j]=1;
            return 1;
        }
    }
}
int main()
{
    freopen("in.txt","r",stdin);
    cin>>n;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            cin>>ch[i][j];
            if(ch[i][j]=='y')
            {
                c[++d][0]=i;c[d][1]=j;
            }
        }
    while(d)
    {
        int i=c[d][0];
        int j=c[d][1];
        for(int k=1;k<=8;k++)
        {
            if(ch[i+dx[k]][j+dy[k]]=='i')
                if(dfs(i+dx[k],j+dy[k],dx[k],dy[k],3))
                vis[i][j]=1;
        }
        d--;
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
        if(vis[i][j])
            cout<<ch[i][j];
        else
            cout<<"*";
        }
        cout<<endl;
    }
    return 0;
}

P2404 自然数的拆分问题
将数字n一层层拆分,利用回溯遍历出多种可能。(最好去模拟一下过程 ,便于理解递归的过程)

#include <iostream>

using namespace std;
int n,a[3005]={1};
void dfs(int s,int g)
{
    int i;
    for(i=a[g-1];i<=s;i++)
    {
        if(i<n)
        {
            a[g]=i;
            s-=i;
            if(s==0)
            {
                for(int j=1;j<=g-1;j++)
                    cout<<a[j]<<"+";
                cout<<a[g]<<endl;
            }
            else
            {
                dfs(s,g+1);
            }
            s+=i;
        }
    }
}
int main()
{
    cin>>n;
    dfs(n,1);
    return 0;
}

P1596 [USACO10OCT]Lake Counting S
一道DFS判断连通块的题目。本题的技巧点在于,一般我们将遍历过为“W”的点开个数组进行标记,本题则直接将“W”变为“.”,非常巧妙。

#include <bits/stdc++.h>

using namespace std;
int n,m,ans;
char ch[105][105];
int dx[9]={0,0,0,1,1,1,-1,-1,-1};
int dy[9]={0,1,-1,0,1,-1,0,-1,1};
void dfs(int x,int y)
{
    ch[x][y]='.';
    for(int i=1;i<=8;i++)
    {
        if(x+dx[i]>=1&&x+dx[i]<=n&&y+dy[i]>=1&&y+dy[i]<=m&&ch[x+dx[i]][y+dy[i]]=='W')
            dfs(x+dx[i],y+dy[i]);
    }
}
int main()
{
    //freopen("in.txt","r",stdin);
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
            cin>>ch[i][j];
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(ch[i][j]=='W'){
                dfs(i,j);
                ans++;
            }
        }
    }
    cout<<ans<<endl;
    return 0;
}

P1162 填涂颜色

涂色问题:注意边界,应该先搜索外面一圈,则的话就会出现错误(边缘处被涂色),这种情况由于边界被范围限制,会被误认为被1包裹。

void dfs(int x,int y)   //两种书写递归的方式,考虑到外围的一圈,这种递归方式要从自己本身搜索
{
    for(int i=0;i<=4;i++)
    {
        if(x+dx[i]>=0&&x+dx[i]<=n+1&&y+dy[i]>=0&&y+dy[i]<=n+1&&vis[x+dx[i]][y+dy[i]]==0)
        {
            vis[x][y]=1; 
            dfs(x+dx[i],y+dy[i]);
        }
    }
}
#include <bits/stdc++.h>
using namespace std;
int dx[5]={0,0,0,1,-1};
int dy[5]={0,1,-1,0,0};
int a[50][50];
int n;
void dfs(int x,int y)
{
    if(x>=0 && x<=n+1 && y>=0&& y<=n+1)
    {
        if(a[x][y]==1||a[x][y]==3)
            return ;
        else
        {
            a[x][y]=3;
            for(int i=1;i<=4;i++)
            dfs(x+dx[i],y+dy[i]);
        }
    }
}
int main()
{
    freopen("in.txt","r",stdin);
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            cin>>a[i][j];
        }
    }
    dfs(0,0);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(a[i][j]==3)
                cout<<0<<" ";
            else if(a[i][j]==0)
                cout<<2<<" ";
            else
                cout<<1<<" ";
        }
        cout<<endl;
    }
    return 0;
}

二分(lower_bound()和upper_bound()复习)

P2249 【深基13.例1】查找

#include <bits/stdc++.h>

using namespace std;
const int maxn=1e6+5;
int a[maxn];
int main()
{
    int n,m;
    cin>>n>>m;
    for(int i=0;i<n;i++)
        cin>>a[i];
    while(m--)
    {
        int tmp;
        cin>>tmp;
        int k=lower_bound(a,a+n,tmp)-a;
        if(tmp==a[k])
            cout<<k+1<<" ";
        else
            cout<<-1<<" ";
    }
    cout<<endl;
    return 0;
}

【算法1-6】二分查找与二分答案

#include <bits/stdc++.h>

using namespace std;
long long a[200005];
int main()
{
    long long n,c;
    cin>>n>>c;
    for(int i=0;i<n;i++)
        cin>>a[i];
    sort(a,a+n);
    long long ans=0;
    for(int i=0;i<n;i++){
    long long a1=upper_bound(a,a+n,a[i]+c)-a;
    long long a2=lower_bound(a,a+n,a[i]+c)-a;
    ans+=a1-a2;
    }
    cout<<ans<<endl;
    return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值