A - Lake Counting POJ - 2386
题意:W是水洼,连起来的W算同一个水洼(是九宫格内的连起来)
解题思路:dfs搜索,搜索不到了就继续,每一个dfs都可以搜到一个水坑,简而言之,总的dfs的次数就是水坑的个数(dfs重新调用的dfs不算)

#include<iostream> #include<algorithm> #include<cstring> #include<sstream> #include<cmath> #include<cstdlib> #include<queue> using namespace std; #define PI 3.14159265358979323846264338327950 int N,M; const int MAX_N=103; char field[MAX_N][MAX_N]; void dfs(int x,int y) { field[x][y]='.'; for(int dx=-1;dx<=1;dx++) { for(int dy=-1;dy<=1;dy++) { int nx=x+dx,ny=y+dy; if(0<=nx && nx<N && 0<=ny && ny<M && field[nx][ny]=='W') dfs(nx,ny); } } return ; } void solve() { int res =0; for(int i=0;i<N;i++) { for(int j=0;j<M;j++) { if(field[i][j]=='W') { dfs(i,j); res++; } } } printf("%d ",res); } int main() { cin>>N>>M; for(int i=0;i<N;i++) for(int j=0;j<M;j++) cin>>field[i][j]; solve(); }
B - N皇后问题 HDU - 2553
在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
你的任务是,对于给定的N,求出有多少种合法的放置方法。
Input共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。Output共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。Sample Input
1 8 5 0
Sample Output
1 92 10
解题思路:可以说是入门的dfs了,直接用数组的i来储存行就不用考虑行的重复了, 只需要进行对列和对角线的判断就好了,先打个表,不然可能会超时哦

#include<iostream> #include<algorithm> #include<cstring> #include<sstream> #include<cmath> #include<cstdlib> #include<queue> using namespace std; #define PI 3.14159265358979323846264338327950 int map[12],a[12],n,sum; int check(int x) { for(int i=0;i<x;i++) { if(map[i]==map[x]||abs(map[i]-map[x])==abs(i-x)) return 0; } return 1; } void dfs(int x) { if(x==n) sum++; else { for(int j=1;j<=n;j++) { map[x]=j; if(check(x)) dfs(x+1); } } } int main() { for(int i=1;i<11;i++) { sum=0; n=i; dfs(0); a[i]=sum; } int n; while(scanf("%d",&n) && n) { printf("%d ",a[n]); } }
C - Catch That Cow POJ - 3278
题目大意:人追牛,人可以加减一步或者两倍
解题思路:就是bfs搜索,注意数组的大小要开两倍

#include<iostream> #include<algorithm> #include<cstring> #include<sstream> #include<cmath> #include<cstdlib> #include<queue> using namespace std; #define PI 3.14159265358979323846264338327950 struct point { int x,y,step; }st; queue<point>q; int vis[200002]; int n,m,flat; int bfs() { while(!q.empty()) { q.pop(); } memset(vis,0,sizeof(vis)); vis[st.x]=1; q.push(st); while(!q.empty()) { point now=q.front(); if(now.x==m) return now.step; q.pop(); for(int j=0;j<3;j++) { point next = now; if(j == 0) next.x=next.x+1; else if(j==1) next.x=next.x-1; else next.x=next.x*2; ++next.step; if(next.x==m) return next.step; if(next.x>=0 && next.x<=200000 && !vis[next.x]) { vis[next.x]=1; q.push(next); } } } return 0; } int main() { while (~scanf("%d %d", &n, &m)) { st.x = n; st.step=0; printf("%d ", bfs()); } return 0; }
D - Dungeon Master POJ - 2251
题意:给你一个多维的迷宫,问能不能可以从起点走到终点,可以上下穿梭层数,也可以东南西北走,都是一秒一个单位,可以到终点就输出步数,不可以就输出那句话
解题思路:其实和普通的二维迷宫差不多,就是多了一个层数,也就是多了两个方向(上下层数)

#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<cstdlib> #include<queue> #include<set> #include<vector> using namespace std; #define INF 0x3f3f3f3f #define eps 1e-10 #define PI acos(-1.0) #define ll long long int const maxn = 35; const int mod = 1e9 + 7; int gcd(int a, int b) { if (b == 0) return a; return gcd(b, a % b); } char map[maxn][maxn][maxn]; int vis[maxn][maxn][maxn]; int k,n,m,sx,sy,sz,ex,ey,ez; int dir[6][3]={{0,0,1},{0,0,-1},{0,1,0},{0,-1,0},{1,0,0},{-1,0,0}}; struct node { int x,y,z,step; }; int check (int x,int y,int z) { if(x<0 || y<0 || z<0 || x>=k || y>=n || z>=m) return 1; else if(map[x][y][z]=='#') return 1; else if(vis[x][y][z]) return 1; return 0; } int bfs() { node a,next; queue<node>que; a.x=sx; a.y=sy; a.z=sz; a.step=0; vis[sx][sy][sz]=1; que.push(a); while(!que.empty()) { a=que.front(); que.pop(); if(a.x == ex && a.y == ey && a.z == ez) return a.step; for(int i=0;i<6;i++) { next=a; next.x=a.x+dir[i][0]; next.y=a.y+dir[i][1]; next.z=a.z+dir[i][2]; if(check(next.x,next.y,next.z)) continue; vis[next.x][next.y][next.z]=1; next.step=a.step+1; que.push(next); } } return 0; } int main() { while(~scanf("%d %d %d",&k,&n,&m)) { if(k==0 && n==0 && m==0) break; for(int i=0;i<k;i++) { for(int j=0;j<n;j++) { scanf("%s",map[i][j]); for(int r=0;r<m;r++) { if(map[i][j][r]=='S') { sx=i;sy=j;sz=r; } else if(map[i][j][r]=='E') { ex=i;ey=j;ez=r; } } } } memset(vis,0,sizeof(vis)); int ans; ans=bfs(); if(ans) printf("Escaped in %d minute(s). ",ans); else printf("Trapped! "); } return 0; }
E - Prime Path HDU - 1973
题意:给你两个四位数,都是素数,每次改变可以改变其中的任何一个数字,但要求改变后的四位数(没有前导零)依然是素数,问最少改变几次可以使得第一个数改为第二个数
思路:可以先用埃氏筛法把1000-9999的所有的素数都选出来,之后就四个位数,每个位数最多改变八次,就搜索一下,我开了isprime和step两个数组,当然也可以开一个结构体,但只改变一个数字需要花点功夫,我是枚举了个位,十位,百位,千位。

#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<cstdlib> #include<queue> #include<set> #include<vector> using namespace std; #define INF 0x3f3f3f3f #define eps 1e-10 #define PI acos(-1.0) #define ll long long int const maxn = 9999; const int mod = 1e9 + 7; int gcd(int a, int b) { if (b == 0) return a; return gcd(b, a % b); } bool isprime[maxn]; int step[maxn]; bool vis[maxn]; int num1,num2; void getprime(int n) { for(int i=0;i<=n;i++) isprime[i]=true; isprime[0]=isprime[1]=false; for(int i=2;i<=n;i++) { for(int j=2*i;j<=n;j=j+i) isprime[j]=false; } } int bfs(int st ) { vis[st]=true; step[st]=0; queue<int>que; que.push(st); while(que.size()) { int p=que.front(); que.pop(); if(p == num2) { return step[num2]; break; } int ge=p % 10; int shi=(p/10)%10; int bai=(p/100)%10; int qian=p/1000; for(int i=0;i<=9;i++) { int next; if(i!=ge) { next=p-ge+i; if(next>=1000 && next<=9999 && isprime[next] && vis[next]==false) { step[next]=step[p]+1; que.push(next); vis[next]=true; // cout<<"ge"; } } if(i!=shi) { next=p-shi*10+i*10; if(next>=1000 && next<=9999 && isprime[next] && vis[next]==false) { step[next]=step[p]+1; que.push(next); vis[next]=true; // cout<<"shi"; } } if(i!=bai) { next=p-bai*100+i*100; if(next>=1000 && next<=9999 && isprime[next] && vis[next]==false) { step[next]=step[p]+1; que.push(next); vis[next]=true; // cout<<"bai"; } } if(i!=qian) { next=p-qian*1000+i*1000; if(next>=1000 && next<=9999 && isprime[next] && vis[next]==false) { step[next]=step[p]+1; que.push(next); vis[next]=true; // cout<<"qian"; } } } } return -1; } int main() { int t; scanf("%d",&t); getprime(9999); while(t--) { memset(vis,false,sizeof(vis)); memset(step,0,sizeof(step)); scanf("%d %d",&num1,&num2); // for(int i=2;i<=9999;i++) // if(isprime[i]) // cout<<i<<" "; int ans=bfs(num1); if(ans>=0) printf("%d ",ans); else printf("Impossible "); } }