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...


  • 相关阅读:
    HDU Railroad (记忆化)
    HDU 1227 Fast Food
    HDU 3008 Warcraft
    asp vbscript 检测客户端浏览器和操作系统(也可以易于升级到ASP.NET)
    Csharp 讀取大文本文件數據到DataTable中,大批量插入到數據庫中
    csharp 在万年历中计算显示农历日子出错
    csharp create ICS file extension
    CSS DIV Shadow
    DataTable search keyword
    User select fontface/color/size/backgroundColor设置 字体,颜色,大小,背景色兼容主流浏览器
  • 原文地址:https://www.cnblogs.com/Eleven-Qian-Shan/p/13096008.html
Copyright © 2011-2022 走看看