返璞归真 重新扫盲(搜索1)

最近打比赛发现了自己很多问题,基础一点都不牢靠,很多显而易见的问题都发现不了,所以重新刷专题。
hdu 1241 戳这里
求最大连通块的问题 这种 迷宫类型的题目 现在真是直接就能敲。

#include <cstdio>
#include <map>
#include <iostream>
#include<bits/stdc++.h>
#define N 20000000
#define ll long long int 
using namespace std;
char map1[105][105];
int vis[105][105];
int dir[8][2]={1,0,-1,0,0,-1,0,1,1,1,1,-1,-1,1,-1,-1};
int n,m,num=0;
bool jg(int x,int y)
{
    for(int i=0;i<8;i++){
        int x1=x+dir[i][0];
        int y1=y+dir[i][1];
        if(x1>=1&&x1<=n&&y1>=1&&y1<=m&&map1[x1][y1]=='@'&&!vis[x1][y1])
            return true;
    }
    return false;
}
void dfs(int x,int y)
{    //cout<<x<<" "<<y<<" "<<num<<endl;
    if(!jg(x,y))
    {        
        return ;
    }
    for(int i=0;i<8;i++){
        int x1=x+dir[i][0];
        int y1=y+dir[i][1];
        if(x1>=1&&x1<=n&&y1>=1&&y1<=m&&map1[x1][y1]=='@'&&!vis[x1][y1]){
            vis[x1][y1]=1;
            dfs(x1,y1);
        //    vis[x1][y1]=0;
        }
    }    
}
int main()
{
    ios::sync_with_stdio(false);
    while(cin>>n>>m)
    {    if(n==0&&m==0)
            break;    
        memset(vis,0,sizeof(vis));
        num=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                cin>>map1[i][j];

        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                {     
                    if(map1[i][j]=='@'&&!vis[i][j]){
                            vis[i][j]=1;
                            dfs(i,j);
                            num++;
                    } 
                }        
        cout<<num<<endl;
    }
}

hdu 1584 戳这里
题面很好懂,一开始也以为是一道大水题,但是后面越想越复杂,想不通怎么去遍历所有情况,只能说水平还是不够,看了很多题解,总结了一下。
解法一:标准的搜索结构,搜索方法无非就是把1->2 2->3…9->10 共有9种情况,每次执行一种情况就修改牌所在的位置,代码的关键我感觉就是回溯的那两次循环,想通以后思路还是很简单的,但是好像比较慢。

#include <cstdio>
#include <map>
#include <iostream>
#include<bits/stdc++.h>
#define N 20000000
#define ll long long int 
using namespace std;
int pos[11];
int vis[11];
int mind=0x3f3f3f3f;
void dfs(int step,int k)
{   int c[11];
    memset(c,0,sizeof(c));
    if(step==9){
        //cout<<k<<endl;
        if(mind>k)
        mind=k;
        return ;
    }
    for(int i=1;i<=9;i++){
        if(!vis[i]){
            vis[i]=1;
            int kk=k+abs(pos[i+1]-pos[i]);
            //cout<<kk<<endl;
            int temp=pos[i];
            for(int j=1;j<=10;j++){
                if(pos[j]==temp){
                    pos[j]=pos[i+1];
                    c[j]=temp;
                }
            }
            dfs(step+1,kk);
            vis[i]=0;
            for(int j=1;j<=10;j++){
                if(c[j]==temp)
                    pos[j]=temp;
            }       
        }
    }
}
int main()
{
    ios::sync_with_stdio(false);
    int t;
    cin>>t;
    while(t--)
    {   memset(vis,0,sizeof(vis));
        for(int i=1;i<=10;i++){
            int x;
            cin>>x;
            pos[x]=i;
        }
        mind=0x3f3f3f3f;
        dfs(0,0);
        cout<<mind<<endl;
    }
}

解法二:这种解法就是二重循环去搜索i->j的所有情况。其实我更倾向于这种做法。。

#include <cstdio>
#include <map>
#include <iostream>
#include<bits/stdc++.h>
#define N 20000000
#define ll long long int 
using namespace std;
int pos[11];
int vis[11];
int mind=0x3f3f3f3f;
void dfs(int step,int k)
{   if(k>mind)
    return ;
    if(step==9){
        //cout<<k<<endl;
        if(mind>k)
        mind=k;
        return ;
    }
    for(int i=1;i<10;i++){
        if(!vis[i]){
            vis[i]=1;
            for(int j=i+1;j<=10;j++){
                if(!vis[j]){
                    dfs(step+1,k+abs(pos[i]-pos[j]));
                    break;
                }   
            }
            vis[i]=0;
        }
    }
}
int main()
{
    ios::sync_with_stdio(false);
    int t;
    cin>>t;
    while(t--)
    {   memset(vis,0,sizeof(vis));
        for(int i=1;i<=10;i++){
            int x;
            cin>>x;
            pos[x]=i;
        }
        mind=0x3f3f3f3f;
        dfs(0,0);
        cout<<mind<<endl;
    }
}

hdu 1175 戳这里

#include <cstdio>
#include <map>
#include <iostream>
#include<cstring>
#define N 20000000
#define ll long long int 
using namespace std;
int n,m,q;
int map1[1005][1005];
int vis[1005][1005];
int dir[4][2]={1,0,-1,0,0,-1,0,1};
int x1,x2,y1,y2;
int dfs(int x,int y,int wan,int direct)
{   //cout<<wan<<endl;
    if(wan>2)
    return 0;
    if(x==x2&&y==y2)
    return 1;
    for(int i=0;i<4;i++){
        int tx=x+dir[i][0];
        int ty=y+dir[i][1];
        if(tx>=1&&tx<=n&&ty>=1&&ty<=m&&(!map1[tx][ty]||(tx==x2&&ty==y2))&&!vis[tx][ty]){
            vis[tx][ty]=1;
            if(direct==i){
                if(dfs(tx,ty,wan,direct))
                return 1;
            }
            else{
                if(dfs(tx,ty,wan+1,i))
                    return 1;
            }
            vis[tx][ty]=0;
        }
    }
    return 0;
}
int main()
{
    while(~scanf("%d%d",&n,&m)){
        if(n==0&&m==0)
        break;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                scanf("%d",&map1[i][j]);
        scanf("%d",&q);
        for(int i=1;i<=q;i++){
            memset(vis,0,sizeof(vis));
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            vis[x1][y1]=1;
            if((map1[x1][y1]!=map1[x2][y2])||map1[x1][y1]==0){
                printf("NO\n");
                continue;
            }
            if(dfs(x1,y1,-1,-1))
            printf("YES\n");
            else
            printf("NO\n");
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值