最近在看这本书,由于我在网上没有找到代码,特地把我的代码贴出来以供参考。由于是手敲,与书上的有所不同,如有错误欢迎指教。
1.6.2 POJ 1852
本题关键在于理解两只蚂蚁相遇后相当于交错而过继续前行。
1 #include <cstdio> 2 #include <iostream> 3 //#include <algorithm> 4 #define max(a,b) ((a)>(b)?(a):(b)) 5 #define min(a,b) ((a)<(b)?(a):(b)) 6 using namespace std; 7 int main(void) 8 { 9 int num; 10 int length, n; 11 scanf("%d",&num); 12 for(int i=0; i<num; i++) 13 { 14 scanf("%d%d",&length,&n); 15 int ma=0, mi=0; 16 int temp; 17 for(int j=0; j<n; j++) 18 { 19 scanf("%d",&temp); 20 mi = max(mi, min(temp, length-temp)); 21 ma = max(ma, max(temp, length-temp)); 22 } 23 printf("%d %d\n",mi, ma); 24 } 25 return 0; 26 }
2.1 搜索
2.1.4 POJ 2386
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> using namespace std; int vis[105][105];//记忆数组 char s[105][105]; int sum; int n, m; void dfs(int x, int y) { if(vis[x][y]==1 || x<0 || x>=n || y<0 || y>=m || s[x][y]=='.') return; vis[x][y] = 1; dfs(x-1, y-1); dfs(x-1, y); dfs(x-1, y+1); dfs(x, y-1); dfs(x, y+1); dfs(x+1, y-1); dfs(x+1, y); dfs(x+1, y+1);//向八个方向搜索 } int main(void) { //freopen("2386.in","r",stdin); scanf("%d%d",&n,&m); sum = 0; getchar();//吃掉'\n' for(int i=0; i<n; i++) for(int j=0; j<=m; j++)//多一个字符吃掉'\n' { scanf("%c",&s[i][j]); } for(int i=0; i<n; i++) for(int j=0; j<m; j++) { if(vis[i][j]==0 && s[i][j]=='W')//有未搜索过的积水点 { sum++; dfs(i, j); } } printf("%d\n",sum); return 0; }
2.1.5迷宫最短路径(bfs)
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <cstring> 5 #include <queue> 6 using namespace std; 7 #define INF 6666666 8 typedef pair<int, int> P; 9 int n, m; 10 char maze[105][105]; 11 int d[105][105];//起点到所有点的最少步数 12 int dx[4]={1,0,-1,0}, dy[4]={0,1,0,-1}; 13 int sx, sy, gx, gy; 14 queue<P> que; 15 void bfs() 16 { 17 while(que.size()) 18 { 19 P p = que.front(); que.pop(); 20 if(p.first==gx && p.second==gy) break;//队列第一个是已经被计算出来的 21 for(int i=0; i<4; i++) 22 { 23 int nx = p.first + dx[i]; 24 int ny = p.second + dy[i];//四个方向走 25 if(nx>=0 && nx<n && ny>=0 && ny<m && maze[nx][ny]!='#' && d[nx][ny]==INF) 26 { 27 que.push(P(nx,ny));//如果可以走,则该点入队列 28 d[nx][ny] = d[p.first][p.second] + 1;//求得该点最短步数 29 } 30 } 31 } 32 } 33 int main(void) 34 { 35 //freopen("2-1-5.in","r",stdin); 36 scanf("%d%d",&n,&m); 37 for(int i=0; i<n; i++) 38 for(int j=0; j<=m; j++) 39 { 40 scanf("%c",&maze[i][j]); 41 d[i][j] = INF; 42 if(maze[i][j] == 'S') { sx = i; sy = j; }//起点 43 if(maze[i][j] == 'G') { gx = i; gy = j; }//终点 44 } 45 d[sx][sy] = 0; 46 que.push(P(sx, sy));//起点入队列 47 bfs(); 48 printf("%d",d[gx][gy]); 49 return 0; 50 }//2015-08-03
2.2 贪心
2.2.3字典序最小问题(POJ3617)
本题关键在于利用正反串的比较来决定选择头字母还是尾字母,另外注意80字符换行。
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> using namespace std; char s[2005], s0[2005], t[2005]; int n, b=0, g=0, b0=0, g0=0, u=0; char c; bool jud(void) { for(int i=0; i<n; i++) { if(s[b+i]!=s0[b0+i]) return (s[b+i]<=s0[b0+i]); } }//用于比较正串和反串来求最优解 int main(void) { //freopen("3617.in","r",stdin); scanf("%d",&n); for(int i=0; i<n; 1) { c = getchar(); if(c>='A' && c<='Z') { s[i++] = c; } } for(int i=0; i<n; i++) { s0[i] = s[n-1-i]; }//s0为s的反串 g=g0=n-1; while(b <= g) { if(jud()==1) {t[u++]=s[b++]; g0--;}//取第一个字母 else {t[u++]=s[g]; g--; b0++;}//取最后一个字母 } for(int i=0; i<n; i++) { putchar(t[i]); if((i+1)%80 == 0) putchar('\n'); } //输出每80字符换行 if((n+1)%80 != 0) putchar('\n'); return 0; }//2015-08-03
2.2.4
1. POJ 3069
本题关键在于找到一个点r范围内的最后一个点和那个点r范围外的第一个点。
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> using namespace std; int a[1005]; int n, r; int main(void) { //freopen("3069.in","r",stdin); while(scanf("%d%d",&r,&n)) { int sum=0; if(n==-1 && r==-1) return 0; for(int i=0; i<n; i++) { scanf("%d",&a[i]);//输入每个点的位置 } sort(a, a+n); int i=0; while(i < n) { int s = a[i++];//从s点开始 while(i<n && a[i]<=s+r) i++; int p = a[i-1]; //找到起始点s区间r内最后一个点 p while(i<n && a[i]<=p+r) i++;//寻找下一个起始点 sum++; } printf("%d\n",sum); } return 0; }//2015-08-03
2. POJ 3253
通过每次连接最短的两块板可以解决。
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <cmath> using namespace std; int a[20005]; int main(void) { //freopen("3253.in","r",stdin); int n; scanf("%d",&n); for(int i=0; i<n; i++) { scanf("%d",&a[i]); } long long res=0, t=0; while(n > 1) { int t1=0, t2=1; if(a[t1]>a[t2]) swap(t1,t2); for(int i=2; i<n; i++) { if(a[i]<a[t1]) swap(a[i], a[t1]); if(a[i]<a[t2]) swap(a[i], a[t2]); } //找出最短板和次短板 t = a[t1]+a[t2]; res+=t; a[t1]+=a[t2]; if(t2!=n-1) swap(a[t2], a[n-1]); n--;//将两块板连接 ,重复此步骤就可解决 } printf("%lld",res); return 0; }//2015-08-04
练习题
2.1
POJ 1979
这道题还是比较简单的,主要要解决掉scanf最后的换行。
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <cstring> 5 using namespace std; 6 int vis[25][25]; 7 char s[25][25]; 8 int n, m, cou;//行数,列数,结果 9 void dfs(int x, int y) 10 { 11 //如果走出矩阵则返回 12 if(x<0 || x>=m || y<0 || y>=n || s[x][y]=='#') return; 13 if(vis[x][y]==1) return; 14 vis[x][y] = 1; 15 if(s[x][y] == '.' || s[x][y] == '@') 16 cou++; 17 //四个方向搜索 18 dfs(x, y-1); 19 dfs(x-1, y); dfs(x+1, y); 20 dfs(x, y+1); 21 22 } 23 int main(void) 24 { 25 int x, y; 26 //freopen("1979.in","r",stdin); 27 while(scanf("%d%d",&n,&m)) 28 { 29 if(n==0 && m==0) return 0; 30 getchar(); //吞掉多余的换行 31 //标记数组清零 32 memset(vis, 0, sizeof(vis)); 33 cou = 0; 34 for(int i=0; i<m; i++) 35 { 36 for(int j=0; j<=n; j++) 37 { 38 scanf("%c",&s[i][j]); 39 if(s[i][j]=='@') 40 { 41 x = i; 42 y = j; 43 } 44 } 45 } 46 dfs(x, y);//从起点开始dfs 47 printf("%d\n",cou); 48 } 49 return 0; 50 }
POJ 3009
石头撞击墙壁后石头停下,墙壁破裂,还是暴力深搜,先判断能否直接到达终点,在搜索所有可行的走法。
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <cstring> 5 using namespace std; 6 int s[25][25]; 7 int result; 8 int sx, sy; 9 int n, m; 10 void dfs(int x, int y, int step, int type) 11 { 12 if(step > 10) return; //超过10步失败 13 //到达目的地 14 if(s[x][y] == 3) 15 { 16 if(result == -1) result = step; 17 else result = min(result, step); 18 return; 19 } 20 //石头把墙撞碎 21 switch(type) 22 { 23 case 1: s[x-1][y] = 0; break; //north 24 case 2: s[x+1][y] = 0; break; //south 25 case 3: s[x][y-1] = 0; break; //west 26 case 4: s[x][y+1] = 0; break; //east 27 } 28 //四处搜索寻找终点 29 for(int i=1; i<=x; i++) 30 { 31 if(s[x-i][y]==1) break; 32 if(s[x-i][y]==3) 33 { 34 dfs(x-i, y, step+1, 0); 35 break; 36 } 37 } 38 for(int i=1; i<m-x; i++) 39 { 40 if(s[x+i][y]==1) break; 41 if(s[x+i][y]==3) 42 { 43 dfs(x+i, y, step+1, 0); 44 break; 45 } 46 } 47 for(int i=1; i<=y; i++) 48 { 49 if(s[x][y-i]==1) break; 50 if(s[x][y-i]==3) 51 { 52 dfs(x, y-i, step+1, 0); 53 break; 54 } 55 } 56 for(int i=1; i<n-y; i++) 57 { 58 if(s[x][y+i]==1) break; 59 if(s[x][y+i]==3) 60 { 61 dfs(x, y+i, step+1, 0); 62 break; 63 } 64 } 65 //四处探索 66 if(x>=1 && s[x-1][y]!=1) 67 for(int i=2; i<=x; i++) 68 if(s[x-i][y]==1) 69 { 70 dfs(x-i+1, y, step+1, 1); 71 break; 72 } 73 if(x+1<m && s[x+1][y]!=1) 74 for(int i=2; i<m-x; i++) 75 if(s[x+i][y]==1) 76 { 77 dfs(x+i-1, y, step+1, 2); 78 break; 79 } 80 if(y>=1 && s[x][y-1]!=1) 81 for(int i=2; i<=y; i++) 82 if(s[x][y-i]==1) 83 { 84 dfs(x, y-i+1, step+1, 3); 85 break; 86 } 87 if(y+1<n && s[x][y+1]!=1) 88 for(int i=2; i<n-y; i++) 89 if(s[x][y+i]==1) 90 { 91 dfs(x, y+i-1, step+1, 4); 92 break; 93 } 94 //墙壁复原 95 switch(type) 96 { 97 case 1: s[x-1][y] = 1; break; 98 case 2: s[x+1][y] = 1; break; 99 case 3: s[x][y-1] = 1; break; 100 case 4: s[x][y+1] = 1; break; 101 } 102 } 103 int main(void) 104 { 105 //freopen("3009.in","r",stdin); 106 while(scanf("%d%d",&n,&m)) //m行n列 107 { 108 if(n==0 && m==0) return 0; 109 result = -1; 110 for(int i=0; i<m; i++) 111 for(int j=0; j<n; j++) 112 { 113 scanf("%d",&s[i][j]); 114 if(s[i][j]==2) {sx=i; sy=j;} 115 } 116 dfs(sx, sy, 0, 0); 117 printf("%d\n",result); 118 } 119 return 0; 120 }