刷題記錄 kuangbin帶你飛專題一:簡單搜索

兩天肝完
感覺自己的暴力水平上升了
碼力大仙!!!

A.POJ1321 棋盤問題

有一個坑點就是可能相鄰層沒有棋盤,所以直接搜全部

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;
int n,m;
int dx[]={0,1,1,1,-1,-1,-1,0,0};
int dy[]={0,1,-1,0,1,-1,0,1,-1};
char a[15][15];
int zx[1005];
int zy[1005],vis[1005];
int t[20][20];
int ans;
void fuck(); 
void dfs(int x,int num){
	if(num==0){
		ans++;
		return;
	}
	for(int i=x;i<n;i++){
		for(int j=0;j<n;j++){
			if(a[i][j]=='#'&&vis[j]==0){
				vis[j]=1;
				dfs(i+1,num-1);
				vis[j]=0;
			}
		}
	}
	return;
}
int main(){
	while(scanf("%d%d",&n,&m)){
		if(n==-1&&m==-1)break;
		for(int i=0;i<n;i++){
			scanf("%s",&a[i]);
		}
		memset(vis,0,sizeof(vis));
		ans=0;
		dfs(0,m);
		cout<<ans<<endl;
	}
	return 0;
}

B.POJ 2251 Dungeon Master

裸三維BFS,沒有坑點
就是POJ很神奇,把bfs過程直接暴力就讓我MLE?
讓我學會了能不寫在主函數裏就一定寫外面

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;
int n,m,k;
char a[35][35][35];
int vis[35][35][35];
int ans;
int sx,sy,sz,zx,zy,zz;
int base[6][3] = { {-1,0,0},{1,0,0},{0,-1,0},{0,1,0},{0,0,-1},{0,0,1} };
struct node{
	int x,y,z,bu;
	friend bool operator<(node a,node b)
    {
        return a.bu>b.bu;
    }
};
bool zou(int x,int y,int z){
	if(x<1||x>k)return false;
	if(y<1||y>m)return false;
	if(z<1||z>n)return false;
	return true;
}
int main(){
	while(scanf("%d%d%d",&n,&m,&k)){
		if(n==0&&m==0&&k==0)break;
		int fa=0;
		memset(vis,0,sizeof(vis));
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				for(int t=1;t<=k;t++){
					cin>>a[t][j][i];
					if(a[t][j][i]=='S'){
						sx=t;
						sy=j;
						sz=i;
					}
					if(a[t][j][i]=='E'){
						zx=t;
						zy=j;
						zz=i;
						a[t][j][i]='.';
					}
				}
			}
		}
		priority_queue<node>q;
		q.push((node){sx,sy,sz,0});
		while(!q.empty()){
			node x=q.top();
			q.pop();
			if(x.x==zx&&x.y==zy&&x.z==zz){
				printf("Escaped in %d minute(s).\n",x.bu);
				fa=1;
				break;
			}
			for(int i=0;i<6;i++){
				int xx=x.x+base[i][0];
				int yy=x.y+base[i][1];
				int zz=x.z+base[i][2];
				if(zou(xx,yy,zz)&&a[xx][yy][zz]!='#'&&vis[xx][yy][zz]==0){
					vis[xx][yy][zz]=1;
					q.push((node){xx,yy,zz,x.bu+1});
				}
			}
		}
		if(fa==0)printf("Trapped!\n");
	}
	return 0;
}

C.POJ 3278 Catch That Cow

一維BFS
控制好邊界就行,純手速秒殺題
(某秒因爲邊界RE了十多發)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;
int n,m,k;
int a[100005];
struct node
{
	int x,num;
};
int vis[100005];
int main(){
	cin>>n>>m;
	queue<node>q;
	q.push((node){n,0});
	vis[n]=1;
	while(!q.empty()){
		node x=q.front();
		q.pop();
		if(x.x==m){
			cout<<x.num;
			return 0;
		}
		if(x.x+1<=100000&&x.x+1>=0&&vis[x.x+1]==0){
			q.push((node){x.x+1,x.num+1});
			vis[x.x+1]=1;
		}
		if(x.x-1<=100000&&x.x-1>=0&&vis[x.x-1]==0){
			q.push((node){x.x-1,x.num+1});
			vis[x.x-1]=1;
		}
		if(x.x*2<=100000&&x.x*2>=0&&vis[x.x*2]==0){
			q.push((node){x.x*2,x.num+1});
			vis[x.x*2]=1;
		}
	}
	return 0;
}

D.POJ 3279 Fliptile

經典開關問題,讓我第一次接觸到了狀態壓縮hhh
如果會狀壓好像也就是個暴力了

#include <cstdio>
#include <cstring>
#include <queue>
#include <iostream>
using namespace std; 
int m,n;
int a[20][20],cal[20][20],out[20][20];
const int dx[]={0,0,1,-1,0};
const int dy[]={1,-1,0,0,0};
int zt(int x,int y){
	int temp=a[x][y];
	for(int i=0;i<5;i++){
		int xx=x+dx[i];
		int yy=y+dy[i];
		if(xx<1||yy<1||xx>n||yy>m)continue;
		temp+=cal[xx][yy];
	}
	return temp%2;
}
int dfs(){
	for(int i=2;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(zt(i-1,j)){
				cal[i][j]=1;
			}
		}
	}
	for(int i=1;i<=m;i++){
		if(zt(n,i))return -1;
	}
	int res=0;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			res+=cal[i][j];
		}
	}
	return res;
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>a[i][j];
		}
	}
	int fa=0;
	int ans=0x3f3f3f3f;
	for(int i=0;i<1<<m;i++){
		memset(cal,0,sizeof(cal));
		for(int j=1;j<=m;j++){
			cal[1][m-j+1]=i>>(j-1)&1;
		}
		int c=dfs();
		if(c>=0&&c<ans){
			fa=1;
			ans=c;
			memcpy(out,cal,sizeof(cal));
		}
	}
	if(!fa)cout<<"IMPOSSIBLE"<<endl;
	else{
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				if(j!=1)cout<<" ";
				cout<<out[i][j];
			}
			cout<<endl;
		}
	}
	return 0;
}  

E.POJ 1426 Find The Multiple

思路就是直接暴力構造搜 *10 和 *10+1
判斷是否能整除

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#define int long long
using namespace std;
int n,m,k,c;
void dfs(unsigned long long x,int t){
	if(t>19)return;
	if(c==1)return;
	if(x%n==0){
		cout<<x<<endl;
		c=1;
		return;
	}
	dfs(x*10,t+1);
	dfs(x*10+1,t+1);
	return;
}
signed main(){
	while(1){
		cin>>n;
		c=0;
		if(n==0)break;
		dfs(1,0);
	}
	return 0;
}

F.POJ 3126 Prime Path

一個有點意思的搜索,不過難度不大,思路就先跑一遍歐拉篩,然後寫一個更換數字的函數,暴力循環判斷是否爲素數,加入隊列中就ok了

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#define int long long
using namespace std;
int n,m,k,c;
int prime[10005];
bool sf[10005];
const int maxn=10005;
int vis[10005];
int cnt=1;
void sushu(){         
    int num=0;       
    memset(sf,true,sizeof(sf));
    for(int i=2;i<=maxn;i++){          
        if(sf[i]) prime[++num]=i;     
        for(int j=1;j<=num;j++){     
            if(i*prime[j]>maxn) break; 
            sf[i*prime[j]]=false;      
            if(i%prime[j]==0) break;   
        }
    }
    sf[1]=false;
    sf[0]=false;
}
int bian(int x,int t,int c){
	int ge,shi,bai,qian;
	ge=x%10;
	x/=10;
	shi=x%10;
	x/=10;
	bai=x%10;
	qian=x/=10;
	if(t==1)return c*1000+bai*100+shi*10+ge;
	else if(t==2)return qian*1000+c*100+shi*10+ge;
	else if(t==3)return qian*1000+bai*100+c*10+ge;
	else if(t==4)return qian*1000+bai*100+shi*10+c;
}
struct node{
	int x,num;
};
void bfs(int x){
	queue<node>q;
	q.push((node){x,0});
	vis[x]=1;
	while(!q.empty()){
		node u=q.front();
		q.pop();
		if(u.x==m){
			cout<<u.num<<endl;
			return;
		}
		for(int i=1;i<=4;i++){
			for(int j=0;j<=9;j++){
				if(i==4&&(j==2||j==4||j==6||j==8))continue;
				if(i==1&&j==0)continue;
				int tt=bian(u.x,i,j);
				if(sf[tt]==true&&vis[tt]==0){
					q.push((node){tt,u.num+1});
					vis[tt]=1;
				}
			}
		}
	}
}
signed main(){
	cin>>k;
	sushu();
//	if(sf[50])cout<<"1";
//	else cout<<"0";
	while(k--){
		cin>>n>>m;
		if(n==m){
			cout<<"0"<<endl;
			continue;
		}
		memset(vis,0,sizeof(vis));
		bfs(n);
	}
	return 0;
}

G.POJ 3087 Shuffle’m Up

傻逼題,難度不夠,英語來湊,直接模擬就行

#include <cstdio>
#include <cstring>
#include <queue>
#include <iostream>
#include <map>
using namespace std; 
int n,c;
string a,b,de;
void dfs(int x){
	map<string,int>m;
	string t=a+b;
	int step=0;
	while(m[t]==0&&t!=de){
		int k=0;
		m[t]=1;
		step++;
		string str=t;
		for(int i=0;i<c;i++){
			str[k]=t[i+c];
			k++;
			str[k]=t[i];
			k++;
		}
		t=str;
	}
	if(t==de){
		cout<<x<<" "<<step<<endl;
	}
	else{
		cout<<x<<" "<<"-1"<<endl;
	}
}
int main(){
	cin>>n;
	int kk=0;
	while(n--){
		kk++;
		cin>>c;
		cin>>a>>b>>de;
		dfs(kk);
	}
	return 0;
}

H.POJ 3414 Pots

這題真的是個超級碼力題
寫完就感覺自己碼力很猛
暴力判斷八種情況,我這裏開結構體裏面放了一個數組表示第一和第二個杯子,並用vector來保存路徑

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
using namespace std;
void fuck();
void shit();
int a,b,c,n,m;
bool vis[102][102];
struct node{
	int w[2],num;
	vector<string>v;
};
int fill(int x,int c){
	return c;
}
int drop(int x){
	return 0;
}
void bfs(int x,int b,int c){
	node t;
	int fa=0;
	t.w[0]=0;
	t.w[1]=0;
	t.num=0;
	vis[0][0]=false;
	queue<node>q;
	q.push(t);
	while(!q.empty()){
		node t=q.front();
		q.pop();
		if(t.w[0]==c||t.w[1]==c){
			cout<<t.num<<endl;
			for(int i=0;i<t.v.size();i++){
				cout<<t.v[i]<<endl;
			}
			fa=1;
			return;
		}
		if(vis[fill(1,a)][t.w[1]]==true){
			vis[fill(1,a)][t.w[1]]=false;
			node a=t;
			a.w[0]=fill(1,x);
			a.num++;
			a.v.push_back("FILL(1)");
			q.push(a);
		}
		if(vis[t.w[0]][fill(2,b)]==true){
			vis[t.w[0]][fill(2,b)]=false;
			node a=t;
			a.w[1]=fill(2,b);
			a.num++;
			a.v.push_back("FILL(2)");
			q.push(a);
		}
		if(vis[0][t.w[1]]==true){
			vis[0][t.w[1]]=false; 
			node a=t;
			a.w[0]=0;
			a.num++;
			a.v.push_back("DROP(1)");
			q.push(a);
		}
		if(vis[t.w[0]][0]==true){
			vis[t.w[0]][0]=false;
			node a=t;
			a.w[1]=0;
			a.num++;
			a.v.push_back("DROP(2)");
			q.push(a);
		}
		if(t.w[0]+t.w[1]>b){
			int cha=t.w[0]+t.w[1]-b;
			if(vis[cha][b]==true){
				vis[cha][b]=false;
				node a=t;
				a.w[0]=cha;
				a.w[1]=b;
				a.num++;
				a.v.push_back("POUR(1,2)");
				q.push(a);
			}
		}
		else{
			int cha=t.w[0]+t.w[1];
			if(vis[0][cha]==true){
				vis[0][cha]=false;
				node a=t;
				a.w[0]=0;
				a.w[1]=cha;
				a.num++;
				a.v.push_back("POUR(1,2)");
				q.push(a);
			}
		}
		if(t.w[0]+t.w[1]>x){
			int cha=t.w[0]+t.w[1]-x;
			if(vis[x][cha]==true){
				vis[x][cha]=false;
				node a=t;
				a.w[0]=x;
				a.w[1]=cha;
				a.num++;
				a.v.push_back("POUR(2,1)");
				q.push(a);
			}
		}
		else{
			int cha=t.w[0]+t.w[1];
			if(vis[cha][0]==true){
				vis[cha][0]=false;
				node a=t;
				a.w[0]=cha;
				a.w[1]=0;
				a.num++;
				a.v.push_back("POUR(2,1)");
				q.push(a);
			}
		}
	}
	if(!fa)cout<<"impossible";
	return;
}
int main(){
	cin>>a>>b>>c;
	memset(vis,true,sizeof(vis));
	bfs(a,b,c);
} 

I.FZU 2150 Fire Game

碼力屑題,讓我自閉了一下午,不想寫

J.UVA 11624 Fire!

對火和人分別bfs,並記錄時間,需要注意的坑點是可能有多團火,然後注意邊界

#include<bits/stdc++.h>
using namespace std;
const int dx[4]={1,-1,0,0};
const int dy[4]={0,0,-1,1};
const int inf=99999999;
int vis[1505][1505],f[1505][1505];
char a[1505][1505];
int n,m,c,tt;
struct node{
	int x,y,t;
}gg;
int main(){
	int t;
	int sx,sy;
	cin>>t;
	while(t--){
		cin>>n>>m;
		c=0;
		queue<node>fire;
		queue<node>q;
		memset(vis,0,sizeof(vis));
		memset(a,'.',sizeof(a));
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				cin>>a[i][j];
				f[i][j]=inf;
				if(a[i][j]=='J'){
					sx=i;
					sy=j;
				}
				if(a[i][j]=='F'){
					fire.push((node){i,j,0});
					vis[i][j]=1;
				}
			}
		}
		while(!fire.empty()){
			node s=fire.front();
			fire.pop();
			for(int i=0;i<4;i++){
				int xx=s.x+dx[i];
				int yy=s.y+dy[i];
				if(xx>=1&&yy>=1&&xx<=n&&yy<=m&&vis[xx][yy]==0&&a[xx][yy]=='.'){
					vis[xx][yy]=1;
					f[xx][yy]=s.t+1;
					fire.push((node){xx,yy,s.t+1});
				}
			}
		}
		memset(vis,0,sizeof(vis));
		q.push((node){sx,sy,0});
		vis[sx][sy]=1;
		while(!q.empty()){
			node s=q.front();
			q.pop();
			if((s.x<=1||s.y<=1||s.x>=n||s.y>=m)&&s.t<f[s.x][s.y]){
				c++;
				cout<<s.t+1<<endl;
				break;
			}
			for(int i=0;i<4;i++){
				int xx=s.x+dx[i];
				int yy=s.y+dy[i];
				if(xx>=1&&yy>=1&&xx<=n&&yy<=m&&vis[xx][yy]==0&&a[xx][yy]=='.'){
					vis[xx][yy]=1;
					q.push((node){xx,yy,s.t+1});
				}
			}
		}
		if(!c){
			cout<<"IMPOSSIBLE"<<endl;
		}
	}
}

K.POJ 3984 迷宮問題

弱智題

L.HDU 1241 Oil Deposits

問有多少個聯通塊
直接循環,dfs走過的點變爲普通路,dfs的次數就是答案

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#define int long long
using namespace std;
int n,m,k,c;
int prime[10005];
bool sf[10005];
const int maxn=10005;
int vis[105][105];
char a[1005][1005];
const int dx[]={1,1,1,-1,-1,-1,0,0};
const int dy[]={1,-1,0,1,-1,0,1,-1};
int cnt=1;
void dfs(int x,int y){
	for(int i=0;i<8;i++){
		int xx=x+dx[i];
		int yy=y+dy[i];
		if(xx>=1&&yy>=1&&xx<=n&&yy<=m&&a[xx][yy]=='@'){
			a[xx][yy]='*';
			dfs(xx,yy);
		}
	}
	return;
}
signed main(){
	while(1){
		cin>>n>>m;
		int ans=0;
		if(n==0&&m==0)break;
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				cin>>a[i][j];
			}
		}
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				if(a[i][j]=='@'){
					a[i][j]='*';
					dfs(i,j);
		//			a[i][j]='*';
					ans++;
				}
			}
		}
		cout<<ans<<endl;
	}
}

M.HDU 1495 非常可樂

又是一個碼力屑題,純暴力bfs
如果變量沒寫好可能容易自閉

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;
int n,m,k,c;
int v[5];
struct node{
	int v[3],num;
	node(int x,int y,int z,int st){
		v[0]=x;
		v[1]=y;
		v[2]=z;
		num=st;
	}
};
bool vis[102][102][102];
const int d1[6] = {0, 0, 1, 1, 2, 2};
const int d2[6] = {1, 2, 0, 2, 0, 1};
void bfs(){
	queue<node>q;
	memset(vis,true,sizeof(vis));
	q.push(node{v[0],0,0,0});
	vis[v[0]][0][0]=false;
	while(!q.empty()){
			node x=q.front();
			q.pop();
			int cnt=0;
			int dd=v[0]/2;
			for(int i=0;i<3;i++){
				if(x.v[i]==dd){
					cnt++;
				}
				if(cnt>=2){
					cout<<x.num<<endl;
					return;
				}
			}
			for(int i=0;i<6;i++){
				node in=x;
				in.num++;
				if(x.v[d1[i]]){
					int cha=v[d2[i]]-x.v[d2[i]];
					if(cha>=x.v[d1[i]]){
						in.v[d2[i]]+=in.v[d1[i]];
						in.v[d1[i]]=0;
					}
					else{
						in.v[d1[i]]-=cha;
						in.v[d2[i]]+=cha;
					}
					if(vis[in.v[0]][in.v[1]][in.v[2]]==true){
						q.push(in);
						vis[in.v[0]][in.v[1]][in.v[2]]=false;
					}
				}
			}
		}
		printf("NO\n");
}
signed main(){
	while(scanf("%d%d%d",&v[0],&v[1],&v[2])){
		if(v[0]==0&&v[1]==0&&v[2]==0)break;
		if(v[0]%2==1){
			cout<<"NO"<<endl;
			continue;
		}
		bfs();
	}
	return 0;
}

N.HDU 2612 Find a way

跑兩個bfs,記錄兩人到達每一個KFC的時間,最後循環求出最小時間(今晚剛吃KFC)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;
int n,m,k,c;
const int maxn=10005;
int vis[205][205];
int cnt,cnt1,cnt2;
char a[1005][1005];
const int dx[]={1,-1,0,0};
const int dy[]={0,0,1,-1};
struct node{
	int x,y,num;
};
int dis[205][205];
signed main(){
	while(scanf("%d%d",&n,&m)!=EOF){
		int ans=99999999;
		vector<int>v1,v2;
		c=0;
		if(n==0&&m==0)break;
		cnt=0,cnt1=0,cnt2=0;
		int sx1,sy1,sx2,sy2;
		memset(dis,0,sizeof(dis));
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				cin>>a[i][j];
				vis[i][j]=0;
				if(a[i][j]=='Y'){
					sx1=i;
					sy1=j;
				}
				if(a[i][j]=='M'){
					sx2=i;
					sy2=j;
				}
				if(a[i][j]=='@'){
					v1.push_back(j);
					v2.push_back(i);
				}
			}
		}
		queue<node>q;
		q.push((node){sx1,sy1,0});
		vis[sx1][sy1]=1;
		while(!q.empty()){
			node x=q.front();
			q.pop();
			if(a[x.x][x.y]=='@'){
				dis[x.x][x.y]+=x.num;
			}
			for(int j=0;j<4;j++){
				int xx=dx[j]+x.x;
				int yy=dy[j]+x.y;
				if(xx>=1&&yy>=1&&xx<=n&&yy<=m&&vis[xx][yy]==0&&a[xx][yy]!='#'){
					vis[xx][yy]=1;
					q.push((node){xx,yy,x.num+1});
				}
			}
		}
		while(!q.empty()){
			q.pop();
		}
		memset(vis,0,sizeof(vis));
		q.push((node){sx2,sy2,0});
		vis[sx2][sy2]=1;
		while(!q.empty()){
			node x=q.front();
			q.pop();
			if(a[x.x][x.y]=='@'){
				dis[x.x][x.y]+=x.num;
			}
			for(int j=0;j<4;j++){
				int xx=dx[j]+x.x;
				int yy=dy[j]+x.y;
				if(xx>=1&&yy>=1&&xx<=n&&yy<=m&&vis[xx][yy]==0&&a[xx][yy]!='#'){
					vis[xx][yy]=1;
					q.push((node){xx,yy,x.num+1});
				}
			}
		}
		ans=99999999;
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				if(dis[i][j]!=0)ans=min(ans,dis[i][j]);
			}
		}
		cout<<ans*11<<endl;
	}
}

雖然這個搜索專題難度不大但是碼力是真的不小…
搜索(×)鍛鍊暴力水平(√)
下一個專題:最短路
加油!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章