zoukankan      html  css  js  c++  java
  • 搜索专题(未完)

    搜索做题总结

    前言:

    因为搜索一直被众OIer称为万能算法——很多题都能用搜索得部分分,所以...所以...嗯,还是重新再刷一遍搜索的题,找找感觉吧!希望在之后的大小比赛考试中能够发挥出来quq


    搜索提单——从基础到提高(未完):

    • 基础

    -- 洛谷P1451 求细胞个数

    -- 洛谷P1141 01迷宫

    -- 洛谷P1683 入门 (此“入门”非彼“入门”,虽然都还挺简单的)

    -- 洛谷P1157 组合的输出

    -- 洛谷P1036 选数

    -- 洛谷P1443 马的遍历

    -- 洛谷P1746 离开中山路

    -- 洛谷P2372 yyy2015c01挑战算周长

    (题目有点长..我这个蒟蒻读了两遍题才读懂QAQ但是题很简单)

    其实这些题很多都是有相似的地方的,而这些相似的地方就是搜索的基础。我们可以把这里作为突破口,然后清晰思路,更利于编程。

    常见的搜索基础类型:“搜索求联通块”、“n个数选k个数”

    • 提高

    -- 洛谷P2360 地下城主

    (虽然标签是普及-,但是我认为比马的遍历那些题会难一点?大概还是因为我蒻)

    -- 洛谷P2298 Mzc和男家丁的游戏

    -- 洛谷P1332 血色先锋队

    -- 洛谷P1434 滑雪

    -- 洛谷P1019 单词接龙

    -- 洛谷P1032 字串变换

    -- 洛谷P3956 棋盘

    (这道题我用广搜没有搞出来,就是太菜,然后使用了WS同学的深搜,这里就推荐一篇他的题解:棋盘 题解

    -- 洛谷P1118 [USACO06FEB]Backward Digit Sums G/S


    部分题目思路:

    • 基础

    -- 求细胞个数、01迷宫、入门、yyy2015c01挑战算周长:“搜索求联通块”

    -- 组合的输出、选数:DFS,“n个数选k个数”

    -- 马的遍历、离开中山路:BFS求最短距离

    • 提高

    -- 地下城主:三维搜索+求最短距离,注意一下数组是先层再行再列(我栽在这1hQAQ),后面给出该题的代码

    -- Mzc和男家丁的游戏、血色先锋队:求最短距离

    -- 滑雪、单词接龙、字串变换、棋盘、Backward Digit Sums G/S:之后会给出代码&题解


    部分题目代码(题解以后再补充qwq):

    • 求细胞个数
    #include <bits/stdc++.h>
    using namespace std;
    int n,m,ans;
    char a[105][105];
    int dx[4]={0,1,0,-1};
    int dy[4]={1,0,-1,0};
    
    inline void bfs(int x,int y) {
    	a[x][y]='0';
    	for(register int i=0;i<4;i++) {
    		int xx=x+dx[i];
    		int yy=y+dy[i];
    		if(xx>n||xx<1||yy>m||yy<1||a[xx][yy]=='0') continue;
    		bfs(xx,yy);
    	}
    }
    
    int main() {
    	scanf("%d%d",&n,&m);
    	for(register int i=1;i<=n;i++) {
    		for(register int j=1;j<=m;j++) {
    			cin>>a[i][j];
    		}
    	}
    	for(register int i=1;i<=n;i++) {
    		for(register int j=1;j<=m;j++) {
    			if(a[i][j]!='0') {
    				ans++;
    				bfs(i,j);
    			}
    		}
    	}
    	printf("%d",ans);
    	return 0;
    }
    
    • 选数
    #include <bits/stdc++.h>
    using namespace std;
    int n,r,sum,ans,num[5000001];
    
    inline bool check(int tot) {
    	for(register int i=2;i*i<=tot;i++) {
    		if(tot%i==0) return false;
    	}
    	return true;
    }
    
    inline void dfs(int now,int k) {
    	for(register int i=k;i<=n;i++) {
    		sum+=num[i];
    		if(now==r) {
    			if(check(sum)) ans++;
    		}
    		else dfs(now+1,i+1);
    		sum-=num[i];
    	}
    }
    
    int main() {
    	scanf("%d%d",&n,&r);
    	for(register int i=1;i<=n;i++) {
    		scanf("%d",&num[i]);
    	}
    	dfs(1,1);
    	printf("%d",ans);
    	return 0;
    }
    
    • 马的遍历
    #include <bits/stdc++.h>
    using namespace std;
    int n,m,sx,sy,pd[4005][4005],ans[4005][4005];
    int dx[8]={1,2,2,1,-1,-2,-2,-1};
    int dy[8]={2,1,-1,-2,-2,-1,1,2};
    
    struct node {
    	int x,y,st;
    } q[160005];
    
    inline void bfs(int xx,int yy) {
    	pd[xx][yy]=1;
    	int front=1,tail=1;
    	q[front].x=xx;
    	q[front].y=yy;
    	q[front].st=0;
    	while(front<=tail) {
    		for(register int i=0;i<8;i++) {
    			int xs=q[front].x+dx[i];
    			int ys=q[front].y+dy[i];
    			if(xs>=1&&xs<=n&&ys>=1&&ys<=m&&pd[xs][ys]==0) {
    				tail++;
    				q[tail].x=xs;
    				q[tail].y=ys;
    				q[tail].st=q[front].st+1;
    				ans[xs][ys]=q[tail].st;
    				pd[xs][ys]=1;
    			}
    		}
    		front++;
    	}
    }
    
    int main() {
    	memset(ans,-1,sizeof(ans));
    	scanf("%d%d%d%d",&n,&m,&sx,&sy);
    	ans[sx][sy]=0;
    	bfs(sx,sy);
    	for(register int i=1;i<=n;i++) {
    		for(register int j=1;j<=m;j++) {
    			printf("%-5d",ans[i][j]);
    		}
    		puts("");
    	}
    	return 0;
    } 
    
    • 地下城主
    #include <bits/stdc++.h>
    using namespace std;
    int L,R,C,sx,sy,sh,ex,ey,eh,sum,ans;
    char a[31][31][31];
    int dx[6]={0,1,0,-1,0,0};
    int dy[6]={1,0,-1,0,0,0};
    int dh[6]={0,0,0,0,1,-1};
    
    struct node {
    	int x,y,h,st;
    } q[100001];
    
    inline void bfs(int xx,int yy,int hh) {
    	a[hh][xx][yy]='#'; //一定要注意先层再行再列!
    	int front=1,tail=1;
    	q[front].x=xx;
    	q[front].y=yy;
    	q[front].h=hh;
    	q[front].st=0;
    	while(front<=tail) {
    		for(register int i=0;i<6;i++) {
    			int xs=q[front].x+dx[i];
    			int ys=q[front].y+dy[i];
    			int hs=q[front].h+dh[i];
    			if(xs>=1&&xs<=R&&ys>=1&&ys<=C&&hs>=1&&hs<=L&&a[hs][xs][ys]!='#') {
    				tail++;
    				q[tail].x=xs;
    				q[tail].y=ys;
    				q[tail].h=hs;
    				q[tail].st=q[front].st+1;
    				if(xs==ex&&ys==ey&&hs==eh) {
    					printf("Escaped in %d minute(s).",q[tail].st);
    					return ;
    				}
    				a[hs][xs][ys]='#';
    			}
    		}
    		front++;
    	}
    	puts("Trapped!");
    }
    
    int main() {
    	scanf("%d%d%d",&L,&R,&C);
    	for(register int i=1;i<=L;i++) {
    		for(register int j=1;j<=R;j++) {
    			for(register int k=1;k<=C;k++) {
    				cin>>a[i][j][k];
    				if(a[i][j][k]=='S') {
    					sx=j;
    					sy=k;
    					sh=i;
    				}
    				if(a[i][j][k]=='E') {
    					ex=j;
    					ey=k;
    					eh=i;
    				}
    			}
    		}
    	}
    	bfs(sx,sy,sh);
    	return 0;
    }
    
    • 血色先锋队
    #include <bits/stdc++.h>
    using namespace std;
    int n,m,a,b,pd[5005][5005],ans[5005][5005];
    int x,y;
    int dx[4]={0,1,0,-1};
    int dy[4]={1,0,-1,0};
    
    struct node {
    	int x,y,st;
    }q[2500005];
    
    inline void bfs(int tot) {
    	int front=1,tail=tot;
    	while(front<=tail) {
    		for(register int i=0;i<4;i++) {
    			int xx=q[front].x+dx[i];
    			int yy=q[front].y+dy[i];
    			if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&pd[xx][yy]==0) {
    				pd[xx][yy]=1;
    				tail++;
    				q[tail].x=xx;
    				q[tail].y=yy;
    				q[tail].st=q[front].st+1;
    				ans[xx][yy]=q[tail].st;
    			}
    		}
    		front++;
    	}
    }
    
    int main() {
    	scanf("%d%d%d%d",&n,&m,&a,&b);
    	for(register int i=1;i<=a;i++) {
    		scanf("%d%d",&x,&y);
    		q[i].x=x;
    		q[i].y=y;
    		q[i].st=0;
    		pd[x][y]=1;
    		ans[x][y]=0;
    	}
    	bfs(a);
    	for(register int i=1;i<=b;i++) {
    		scanf("%d%d",&x,&y);
    		printf("%d
    ",ans[x][y]);
    	}
    	return 0;
    }
    
    • 滑雪
    #include <bits/stdc++.h>
    using namespace  std;
    int c,r,sum=0,a[101][101],f[101][101];
    int dx[5]={0,0,-1,0,1};
    int dy[5]={0,1,0,-1,0};
    inline void dfs(int x,int y) {
    	f[x][y]=1;
    	int tot=0,ans=1;
    	for(int i=1;i<=4;i++) {
    		int xx=x+dx[i];
    		int yy=y+dy[i];
    		if(xx>=1&&xx<=r&&yy>=1&&yy<=c&&a[xx][yy]>a[x][y]) {
    			if(f[xx][yy]==0) {
    				dfs(xx,yy);
    			}
    			f[x][y]=max(f[x][y],f[xx][yy]+1);
    		}
    	}
    }
    int main() {
    	cin>>r>>c;
    	for(int i=1;i<=r;i++) {
    		for(int j=1;j<=c;j++) {
    			cin>>a[i][j];
    		}
    	}
    	for(int i=1;i<=r;i++) {
    		for(int j=1;j<=c;j++) {
    			if(f[i][j]==0) dfs(i,j);
    			sum=max(sum,f[i][j]);
    		}
    	}
    	cout<<sum;
    	return 0;
    }
    

    这道题我们用字母来模拟一下自上而下的合并过程,然后...你就会发现和某某三角(杨辉三角啦)有那么一点点的像,模拟如下:

    先来看看n=4的情况
    a    b    c    d
    a+b   b+c   c+d
    a+2b+c  b+2c+d
    a+3b+3c+d(sum)
    
    再来看看n=6的情况
    a      b      c      d      e     f
    a+b     b+c     c+d     d+e     e+f
    a+2b+c    b+2c+d    c+2d+e    d+2e+f
    a+3b+3c+d   b+3c+3d+e   c+3d+3e+f
    a+4b+6c+4d+e  b+4c+6d+4e+f
    a+5b+10c+10d+5e+f(sum)
    
    然后我们来看看某某三角
    【1】1
    【2】1 1
    【3】1 2 1
    【4】1 3 3 1
    【5】1 4 6 4 1
    【6】1 5 10 10 5 1
    ······
    

    将两者进行对比,我们就会发现:
    sum表达式中各个项的系数就是杨辉三角中第n行的数字

    #include <bits/stdc++.h>
    using namespace std;
    int n,sum,yh[21][21],a[200010],flag[200010];
    
    inline void dfs(int k,int now) {  
    	if(now>sum) return ; //剪枝,如果当前数字和已经大于sum,直接退出 
    	if(k>n&&now==sum) {
    		for(register int i=1;i<=n;i++) printf("%d ",a[i]);
    		exit(0); //找到了就直接结束程序 
    	}
    	for(register int i=1;i<=n;i++) {
    		if(flag[i]==0) { //判重 
    			a[k]=i; //存数 
    			flag[i]=1;
    			dfs(k+1,now+i*yh[n][k]); //核心! 
    			flag[i]=0;
    		}
    	}
    }
    
    int main() {
    	scanf("%d%d",&n,&sum);
    	yh[1][1]=1;
    	for(register int i=2;i<=n;i++) { //预处理杨辉三角 
    		for(register int j=1;j<=i;j++) {
    			yh[i][j]=yh[i-1][j]+yh[i-1][j-1];
    		}
    	}
    	/*for(register int i=1;i<=n;i++) {  打印杨辉三角 
    		for(register int j=1;j<=i;j++) {
    			cout<<yh[i][j]<<" ";
    		}
    		cout<<endl;
    	}*/
    	dfs(1,0);
    	return 0;
    }
    

    To be continued...


  • 相关阅读:
    Mac OS X 10.10(yosemite)更新后,cocoapods出错, 及cocoapods更新至0.34后, 错误情况整理
    如何删除已上线的IAP项
    Automator一键生成所需的iOS 图片icon
    django-simple-captcha 组件使用
    git 本地推送远程仓库报错: error: failed to push some refs to 'https://github.com/yangtuothink/mxonline.git'
    git 提交报错 : The file will have its original line endings in your working directory.
    Django 静态文件相关设置
    Xadmin 组件基础使用以及全局配置
    安装 xadmin 报错: Command "python setup.py egg_info" failed with error code 1 in C:UsersPythonAppDataLocalTemppip-install-1k1byg0pxadmin
    IntegrityError at /admin/users/userprofile/add/ (1452, 'Cannot add or update a child row: a foreign key constraint fails (`mxonline`.`django_admin_log`, CONSTRAINT `django_admin_log_user_id_c564eba6_
  • 原文地址:https://www.cnblogs.com/Eleven-Qian-Shan/p/13096008.html
Copyright © 2011-2022 走看看