zoukankan      html  css  js  c++  java
  • 【kuangbin专题一】简单搜索

    [2020.12.21 ]

    自从上个礼拜打铁以来,感觉整个人都不对劲。

    最近几天打了一些比赛,找回了一点感觉。

    这段时间到考试前,我打算刷一刷kuangbin题单,毕竟这是开学的时候就立下的Flag...

    ...只完成了最后一个不用脑子的...

    实在是太草了

    一、 搜索专题

    A - 棋盘问题

    #include<cstdio>
    using namespace std;
    const int N = 1e5 + 10;
    
    int n, k, ans;
    char mp[10][10];
    int col[10];
    
    void dfs(int now,int sum){
    	if(sum == k){
    		ans++;return;
    	}
    	if (now > n)return;
    	
    	for(int i = 1;i <= n;i++){
    		if(mp[now][i] == '#' and !col[i]){
    			col[i] = 1;
    			dfs(now + 1, sum + 1);
    			col[i] = 0;
    		}
    	}
    	dfs(now + 1, sum);
    }
    int main(){
    	while(~scanf("%d%d",&n,&k) and n != -1){
    		for (int i = 1;i <= n;i++) scanf("%s", mp[i] + 1);
    		ans = 0;
    		dfs(0, 0);
    		printf("%d
    ", ans);
    	}
    }
    

    B - Dungeon Master

    三维迷宫bfs,我属实有点拉跨了。

    我开始一直MLE还埋怨是不是poj的问题,后来发现自己bfs没有开vis数组...

    后来输出的时候没有加 . (一个优雅的英文句号) ...

    /*
     * @Author: zhl
     * @LastEditTime: 2020-12-21 15:01:56
     */
    #include<cstdio>
    #include<queue>
    using namespace std;
    
    int h, n, m;
    
    char mp[40][40][40];
    typedef struct {
        int h, x, y;
    }p;
    
    const int dh[] = { 1,-1,0,0,0,0 };
    const int dx[] = { 0,0,1,-1,0,0 };
    const int dy[] = { 0,0,0,0,1,-1 };
    
    p st, ed;
    
    int main() {
    	while (scanf("%d%d%d", &h, &n, &m) and h != 0) {
    		for (int i = 1; i <= h; i++) {
    			for (int j = 1; j <= n; j++) {
    				scanf("%s", mp[i][j] + 1);
    				for (int k = 1; k <= m; k++) {
    					if (mp[i][j][k] == 'S')st = { i,j,k };
    					if (mp[i][j][k] == 'E')ed = { i,j,k };
    				}
    			}
    		}
    		queue<p>Q; Q.push(st);
    		int ans = -1, now = 0;
    		while (not Q.empty()) {
    			int sz = Q.size();
    			while (sz--) {
    				p tp = Q.front(); Q.pop();
    				if (tp == ed) {
    					ans = now;
    					goto END;
    				}
    				for (int i = 0; i < 6; i++) {
    					int nh = tp.h + dh[i];
    					int nx = tp.x + dx[i];
    					int ny = tp.y + dy[i];
    					if (nh > h or nh < 1 or nx > n or nx < 1 or ny > m or ny < 1)continue;
    					if (mp[nh][nx][ny] == '#')continue;
    					Q.push({ nh,nx,ny });
    				}
    			}
    			now++;
    		}
    	END:
    		if (ans == -1)puts("Trapped!");
    		else printf("Escaped in %d minute(s).
    ", ans);
    	}
    }
    

    C - Catch That Cow

    /*
     * @Author: zhl
     * @LastEditTime: 2020-12-21 15:19:05
     */
    #include<cstdio>
    #include<queue>
    using namespace std;
    int n, k;
    int vis[100010];
    int main() {
    	scanf("%d%d", &n, &k);
    	queue<int>Q; Q.push(n); vis[n] = 1;
    	int ans = 0;
    	while (not Q.empty()) {
    		int sz = Q.size();
    		while (sz--) {
    			int tp = Q.front(); Q.pop();
    			if (tp == k) {
    				printf("%d
    ", ans);
    				return 0;
    			}
    			if (tp > 0 and !vis[tp - 1])vis[tp - 1] = 1, Q.push(tp - 1);
    			if (tp < 100009 and !vis[tp + 1])vis[tp + 1] = 1, Q.push(tp + 1);
    			if (tp * 2 < 100010 and !vis[tp * 2])vis[tp * 2] = 1, Q.push(2 * tp);
    		}
    		ans++;
    	}
    	puts("-1");
    
    }
    

    D - Fliptile

    很垃圾的一份代码,只有一个剪枝。

    代码也写的没法看...

    我不应该瞧不起这些题目...

    其实好像第一行确定了方案就确定了,好像可以暴力枚举第一行

    好像也差不多

    /*
     * @Author: zhl
     * @LastEditTime: 2020-12-21 15:33:28
     * @res: 641ms / limit 2000ms
     */
    
    #include<cstdio>
    
    bool flag;
    int mp[20][20], n, m;
    const int dx[] = { 1,0,-1,0,0 };
    const int dy[] = { 0,1,0,-1,0 };
    int ans[20][20], res[20][20], mx;
    void dfs(int x, int y,int sum) {
    	if (x > n) {
    		for (int i = 1; i <= n; i++) {
    			for (int j = 1; j <= m; j++)if (mp[i][j] == 1)return;
    		}
    		flag = true;
    		if (sum < mx) {
    			mx = sum;
    			for (int i = 1; i <= n; i++) {
    				for (int j = 1; j <= m; j++) {
    					res[i][j] = ans[i][j];
    					//printf("%d%c", ans[i][j], " 
    "[j == m]);
    				}
    			}
    		}
    		else if (sum == mx) {
    			bool le = true;
    			for (int i = 1; i <= n; i++) {
    				for (int j = 1; j <= m; j++) {
    					if (ans[i][j] > res[i][j])le = false;
    				}
    			}
    			if (le) {
    				for (int i = 1; i <= n; i++) {
    					for (int j = 1; j <= m; j++) {
    						res[i][j] = ans[i][j];
    						//printf("%d%c", ans[i][j], " 
    "[j == m]);
    					}
    				}
    			}
    		}
    		return;
    	}
    	if (x > 1) {
    		if (mp[x - 1][y] == 0) {
    			//if (x == n and y > 1 and mp[x][y - 1] == 1)return;
    			ans[x][y] = 0, dfs(x + (y == m), (y == m) ? 1 : y + 1, sum);
    		}
    		else {
    			//if (x == n && y > 1 && mp[x][y - 1] == 0)return;
    			ans[x][y] = 1;
    			for (int i = 0; i < 5; i++)mp[x + dx[i]][y + dy[i]] ^= 1;
    			dfs(x + (y == m), (y == m) ? 1 : y + 1, sum + 1);
    			for (int i = 0; i < 5; i++)mp[x + dx[i]][y + dy[i]] ^= 1;
    		}
    	}
    	else {
    		ans[x][y] = 0;
    		dfs(x + (y == m), (y == m) ? 1 : y + 1, sum);
    
    		ans[x][y] = 1;
    		for (int i = 0; i < 5; i++)mp[x + dx[i]][y + dy[i]] ^= 1;
    		dfs(x + (y == m), (y == m) ? 1 : y + 1, sum + 1);
    		for (int i = 0; i < 5; i++)mp[x + dx[i]][y + dy[i]] ^= 1;
    	}
    }
    int main() {
    	scanf("%d%d", &n, &m);
    	for (int i = 1; i <= n; i++)for (int j = 1; j <= m; j++)scanf("%1d", mp[i] + j);
    	mx = 1000000;
    	dfs(1, 1, 0);
    	if (!flag)puts("IMPOSSIBLE");
    	else {
    		for (int i = 1; i <= n; i++) {
    			for (int j = 1; j <= m; j++) {
    				//res[i][j] = ans[i][j];
    				printf("%d%c", res[i][j], " 
    "[j == m]);
    			}
    		}
    	}
    }
    

    我一番压行操作后

    我悟出一个道理

    在DFS的时候,在进入dfs前剪枝和进入dfs后再剪枝是不一样的,前则要快不少。

    /*
     * @Author: zhl
     * @LastEditTime: 2020-12-21 15:59:09
     * @res: 782ms / limit: 2000ms
     */
    
    #include<cstdio>
    #define max(a,b) (a>b?a:b)
    
    bool flag;
    int mp[20][20], n, m;
    const int dx[] = { 1,0,-1,0,0 };
    const int dy[] = { 0,1,0,-1,0 };
    int ans[20][20], res[20][20], mx;
    void dfs(int x, int y, int sum) {
    	if (x > n) {
    		if (sum > mx)return;
    		for (int i = 1; i <= n; i++)for (int j = 1; j <= m; j++)if (mp[i][j] == 1 || (sum == mx && (ans[i][j] > res[i][j])))return;
    		flag = true; mx = sum;
    		for (int i = 1; i <= n; i++)for (int j = 1; j <= m; j++)res[i][j] = ans[i][j];
    		return;
    	}
    	if(x == 1 || mp[x-1][y] == 0)ans[x][y] = 0,dfs(x + (y == m), (y == m) ? 1 : y + 1, sum);
    	if (x == 1 || mp[x - 1][y] == 1) {
    		for (int i = 0; i < 5; i++)mp[x + dx[i]][y + dy[i]] ^= 1;
    		ans[x][y] = 1;
    		dfs(x + (y == m), (y == m) ? 1 : y + 1, sum + 1);
    		for (int i = 0; i < 5; i++)mp[x + dx[i]][y + dy[i]] ^= 1;
    	}
    }
    int main() {
    	scanf("%d%d", &n, &m);
    	for (int i = 1; i <= n; i++)for (int j = 1; j <= m; j++)scanf("%1d", mp[i] + j);
    	mx = 751404976; dfs(1, 1, 0);
    	if (!flag)puts("IMPOSSIBLE");
    	else {
    		for (int i = 1; i <= n; i++)for (int j = 1; j <= m; j++)printf("%d%c", res[i][j], " 
    "[j == m]);
    	}
    }
    

    E - Find The Multiple

    暴力算了一些数据发现位数都比较小,于是直接从低位搜到高位。

    裸的搜索可以直接交上去,跑了 938ms

    发现 m == 198 的时候搜的答案是 1111111111111111110,可以直接加个特判。

    跑了 344ms

    当然也可以直接打表光速过题。

    #include<cstdio>
    /* status : 938ms / 1000ms */
    using namespace std;
    
    typedef long long ll;
    ll ans[300];
    ll get(ll j) {
        if (ans[j])return ans[j];
        for (int i = 1;i < 1 << 20;i++) {
            ll base = 1, now = 0;
            for (int k = 0;k < 20;k++) {
                if ((i >> k) & 1)now = (now + base) % j;
                base = base * 10 % j;
            }
            if (now == 0)return ans[j] = i;
        }
    }
    void print(ll x) {
        if (!x)return;
        print(x >> 1);
        if (x & 1)putchar('1');else putchar('0');
    }
    int main() {
        int n;
        while (scanf("%d", &n) && n > 0) {
            print(get(n));puts("");
        }
    }
    
    #include<cstdio>
    /* 加了特判  status: 344ms / 1000ms  */
    using namespace std;
    
    typedef long long ll;
    ll ans[300];
    ll get(ll j) {
    	if (ans[j])return ans[j];
    	for (int i = 1; i < 1 << 19; i++) {
    		ll base = 1, now = 0;
    		for (int k = 0; k < 19; k++) {
    			if ((i >> k) & 1)now = (now + base) % j;
    			base = base * 10 % j;
    		}
    		if (now == 0)return ans[j] = i;
    	}
    }
    void print(ll x) {
    	if (!x)return;
    	print(x >> 1);
    	if (x & 1)putchar('1'); else putchar('0');
    }
    int main() {
    	int n;
    	while (scanf("%d", &n) && n > 0) {
    		if (n == 198) {
    			puts("1111111111111111110"); continue;
    		}
    		print(get(n)); puts("");
    	}
    }
    

    F - Prime Path

    简单bfs,先建边就可以

    #include<cstdio>
    #include<queue>
    #include<map>
    #include<vector>
    
    using namespace std;
    
    bool judge(int x) {
    	for (int i = 2; i * i <= x; i++)if (x % i == 0)return false;
    	return true;
    }
    bool ok(int x, int y) {
    	int dif = 0;
    	for (int i = 0; i < 4; i++) {
    		if (x % 10 != y % 10)dif++;
    		x /= 10; y /= 10;
    	}
    	return dif == 1;
    }
    int T, x, y;
    map<int, vector<int> >G;
    int main() {
    	vector<int>L;
    	for (int i = 1000; i <= 9999; i++) {
    		if (judge(i))L.push_back(i);
    	}
    	int n = L.size();
    	for (int i = 0; i < n; i++) {
    		for (int j = 0; j < i; j++) {
    			if (ok(L[i], L[j])) {
    				G[L[i]].push_back(L[j]);
    				G[L[j]].push_back(L[i]);
    			}
    		}
    	}
    	scanf("%d", &T);
    	while (T--) {
    		scanf("%d%d", &x, &y);
    		queue<int>Q;
    		int ans = -1, now = 0;
    		Q.push(x); map<int, int>vis; vis[x] = 1;
    
    		while (!Q.empty()) {
    			int sz = Q.size();
    			while (sz--) {
    				int tp = Q.front(); Q.pop();
    				if (tp == y) {
    					ans = now;
    					break;
    				}
    				for (int i = 0; i < G[tp].size();i++) {
    					int v = G[tp][i];
    					if (!vis[v]) {
    						Q.push(v);
    						vis[v] = 1;
    					}
    				}
    			}
    			if (ans != -1)break;
    			now++;
    		}
    		if (ans == -1)puts("Impossible");
    		else {
    			printf("%d
    ", ans);
    		}
    	}
    }
    

    G - Shuffle'm Up

    直接模拟就可以,注意要手动加一个 ''

    /*
     * @Author: zhl
     * @LastEditTime: 2020-12-22 09:57:16
     */
    #include<cstdio>
    #include<cstring>
    int T, n;
    char s[200], p[200], tm[300], st[300], ed[300];
    
    int main() {
    	scanf("%d", &T); int c = 0;
    	while (T--) {
    		scanf("%d", &n);
    		scanf("%s", s + 1);
    		scanf("%s", p + 1);
    		scanf("%s", ed + 1);
    		for (int i = 1; i <= n; i++) {
    			st[2 * i - 1] = p[i];
    			st[2 * i] = s[i];
    		}
    		st[2 * n + 1] = 0; //!!!
    		strcpy(tm + 1, st + 1);
    		int ans = -1, now = 1;
    		while (1) {
    			for (int i = 1; i <= n; i++) {
    				s[i] = tm[i]; p[i] = tm[i + n];
    			}
    			if (!strcmp(tm + 1, ed + 1)) {
    				ans = now;
    				break;
    			}
    			if (!strcmp(tm + 1, st + 1) && now != 1) {
    				break;
    			}
    			for (int i = 1; i <= n; i++) {
    				tm[2 * i - 1] = p[i];
    				tm[2 * i] = s[i];
    			}
    			now++;
    		}
    		printf("%d %d
    ", ++c, ans);
    	}
    }
    

    H - Pots

    刚开始以为会很难写,其实细细想一想实现起来也不是特别难。

    比较锻炼代码能力

    /*
     * @Author: zhl
     * @LastEditTime: 2020-12-22 19:27:20
     */
    #include<cstdio>
    #include<map>
    #include<queue>
    #include<cstring>
    #define min(a,b) (a<b?a:b)
    using namespace std;
    int A, B, C;
    struct st {
    	int a, b;
    	st() {}
    	st(int _a, int _b) { a = _a, b = _b; }
    	bool operator < (const st& x)const {
    		if (a != x.a)return a < x.a;
    		return b < x.b;
    	}
    }ed;
    int vis[200][200];
    map<st, st>pre;
    char pre_op[200][200][200];
    const char op[6][200] = {
    	"FILL(1)","FILL(2)","DROP(1)",
    	"DROP(2)","POUR(1,2)","POUR(2,1)"
    };
    st res[6];
    void operate(st x) {
    	res[0] = st(A, x.b); res[1] = st(x.a, B);
    	res[2] = st(0, x.b); res[3] = st(x.a, 0);
    	int mx = min(x.a, B - x.b); res[4] = st(x.a - mx, x.b + mx);
    	mx = min(A - x.a, x.b); res[5] = st(x.a + mx, x.b - mx);
    }
    void print(st x) {
    	if (x.a == 0 and x.b == 0)return;
    	print(pre[x]);
    	printf("%s
    ", pre_op[x.a][x.b]);
    }
    int main() {
    	scanf("%d%d%d", &A, &B, &C);
    	queue<st>Q;
    	Q.push({ 0,0 }); vis[0][0] = 1;
    	int ans = -1, now = 0;
    	while (not Q.empty()) {
    		int sz = Q.size();
    		while (sz--) {
    			st tp = Q.front(); Q.pop();
    			//printf("(%d , %d)
    ", tp.a, tp.b);
    			if (tp.a == C or tp.b == C) {
    				ans = now;
    				ed = tp;
    				break;
    			}
    			operate(tp);
    			for (int i = 0; i < 6; i++) {
    				if (vis[res[i].a][res[i].b])continue;
    				vis[res[i].a][res[i].b] = 1;
    				pre[res[i]] = tp;
    				strcpy(pre_op[res[i].a][res[i].b], op[i]);
    				Q.push(res[i]);
    			}
    		}
    		if (ans != -1)break;
    		now++;
    	}
    	if (ans == -1)puts("impossible");
    	else {
    		printf("%d
    ", ans);
    		print(ed);
    	}
    }
    

    I - Fire Game

    看到数据量这么小,脑子里不要带东西。

    直接用最裸的暴力就可以了,不需要任何优化

    /*
     * @Author: zhl
     * @LastEditTime: 2020-12-22 20:00:09
     */
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #define min(a,b) (a<b?a:b)
    using namespace std;
    int T, n, m;
    char mp[20][20];
    struct point {
    	int x, y;
    	point() {}
    	point(int _x, int _y) {
    		x = _x, y = _y;
    	}
    };
    int vis[20][20];
    const int dx[] = { 1,0,-1,0 };
    const int dy[] = { 0,1,0,-1 };
    
    int cal(point st1, point st2) {
    	int ans = 0; memset(vis, 0, sizeof vis);
    	queue<point>Q; Q.push(st1); Q.push(st2);
    	vis[st1.x][st1.y] = vis[st2.x][st2.y] = 1;
    	while (!Q.empty()) {
    		int sz = Q.size();
    		while (sz--) {
    			point tp = Q.front(); Q.pop();
    			for (int i = 0; i < 4; i++) {
    				int nx = tp.x + dx[i], ny = tp.y + dy[i];
    				if (nx < 1 or nx > n or ny < 1 or ny > m or mp[nx][ny] != '#' or vis[nx][ny])continue;
    				vis[nx][ny] = 1;
    				Q.push(point(nx, ny));
    			}
    			
    		}ans++;
    	}
    	for (int i = 1; i <= n; i++)for (int j = 1; j <= m; j++)if (mp[i][j] == '#' and !vis[i][j])return 0x3f3f3f3f;
    	return ans - 1;
    }
    int main() {
    	scanf("%d", &T); int c = 0;
    	while (T--) {
    		scanf("%d%d", &n, &m);
    		for (int i = 1; i <= n; i++)scanf("%s", mp[i] + 1);
    		int ans = 0x3f3f3f3f;
    		for (int i = 1; i <= n; i++) {
    			for (int j = 1; j <= m; j++) {
    				if (mp[i][j] != '#')continue;
    				for (int x = 1; x <= n; x++) {
    					for (int y = 1; y <= m; y++) {
    						if (mp[x][y] != '#')continue;
    						ans = min(ans, cal(point(i, j), point(x, y)));
    					}
    				}
    			}
    		}
    		if (ans == 0x3f3f3f3f)ans = -1;
    		printf("Case %d: %d
    ", ++c, ans);
    	}
    }
    

    J - Fire!

    先bfs出每个点到火源的距离,再对joe进行bfs一次,若距离joe的距离大于等于到火的距离则不能入队,看能否到达边缘就可以,Uva挂了不知道对没对

    /*
     * @Author: zhl
     * @LastEditTime: 2020-12-23 10:41:10
     */
    #include<bits/stdc++.h>
    using namespace std;
    
    int T, n, m;
    char mp[1010][1010];
    
    struct p {
    	int x, y;
    };
    p fire, joe;
    //map<p, int>dis, vis;
    int dis[1010][1010], vis[1010][1010];
    const int dx[] = { 1,0,-1,0 };
    const int dy[] = { 0,1,0,-1 };
    
    int main() {
    	scanf("%d", &T);
    	while (T--) {
    		scanf("%d%d", &n, &m);
    		queue<p>Q; 
    		memset(dis, 0, sizeof dis);
    		memset(vis, 0, sizeof vis);
    		for (int i = 1; i <= n; i++) {
    			scanf("%s", mp[i] + 1);
    			for (int j = 1; j <= m; j++) {
    				if (mp[i][j] == 'J')joe = { i,j };
    				if (mp[i][j] == 'F')Q.push({ i,j }), vis[i][j] = 1;
    			}
    		}
    		
    		while (not Q.empty()) {
    			int sz = Q.size();
    			while (sz--) {
    				p tp = Q.front(); Q.pop();
    				for (int i = 0; i < 4; i++) {
    					int nx = tp.x + dx[i], ny = tp.y + dy[i];
    					if (nx < 1 or nx > n or ny < 1 or ny > m or mp[nx][ny] == '#' or vis[nx][ny])continue;
    					vis[nx][ny] = 1;
    					dis[nx][ny] = dis[tp.x][tp.y] + 1;
    					Q.push({ nx,ny });
    				}
    			}
    		}
    		int ans = -1, now = 0; 
    		Q.push(joe); memset(vis,0,sizeof vis); vis[joe.x][joe.y] = 1;
    		while (not Q.empty()) {
    			int sz = Q.size();
    			while (sz--) {
    				p tp = Q.front(); Q.pop();
    				if (tp.x == 1 or tp.x == n or tp.y == 1 or tp.y == m) {
    					ans = now;
    					break;
    				}
    				for (int i = 0; i < 4; i++) {
    					int nx = tp.x + dx[i], ny = tp.y + dy[i];
    					if (mp[nx][ny] == '#' or (dis[nx][ny] != 0 and now + 1 >= dis[nx][ny]) or vis[nx][ny])continue;
    					vis[nx][ny] = 1;
    					Q.push({ nx,ny });
    				}
    			}
    			if (ans != -1)break;
    			now++;
    		}
    		if (ans == -1)puts("IMPOSSIBLE");
    		else printf("%d
    ", ans + 1);
    	}
    }
    

    K - 迷宫问题

    这个题我开始觉得太水了,不想写,结果debug,滴了半个多小时

    且听我细细道来

    对于样例

    0 1 0 0 0
    0 1 0 1 0
    0 0 0 0 0
    0 1 1 1 0
    0 0 0 1 0
    

    我在下面的代码片加了断点,发现当 nxt == {3,2} 的时候,被 continue 略过去了

    我开始改成了 vis.count(nxt) 发现没啥变化,我把 vis[nxt] 去掉,就没有被略过去

    int nx = tp.x + dx[i], ny = tp.y + dy[i];
    p nxt = { nx,ny };
    if (nx < 1 or nx > 5 or ny < 1 or ny > 5 or mz[nx][ny] == 1 or vis[nxt])continue;
    

    后来我一想,原来是重载的问题

    bool operator < (const point& b)const {
    	//return x < b.x;
    	return x == b.x ? y < b.y : x < b.x;
    }
    

    注释掉的是最开始的,因为最开始的时候map报错了,我意识到是要重载运算符,我就随便重载了一下。

    队友说是要满足自反性

    /*
     * @Author: zhl
     * @LastEditTime: 2020-12-22 10:51:10
     */
    #include<cstdio>
    #include<map>
    #include<queue>
    
    using namespace std;
    int mz[10][10];
    typedef struct point {
    	int x, y;
    	bool operator == (point b) {
    		return x == b.x and y == b.y;
    	}
    	bool operator < (const point& b)const {
    		//return x < b.x;
    		return x == b.x ? y < b.y : x < b.x;
    	}
    }p;
    p st, ed;
    map<p, p>pre;
    map<p, int>vis;
    const int dx[] = { 1,0,-1,0 };
    const int dy[] = { 0,1,0,-1 };
    void print(p x) {
    	if (x == st) {
    		printf("(%d, %d)
    ", x.x - 1, x.y - 1);
    		return;
    	}
    	print(pre[x]);
    	printf("(%d, %d)
    ", x.x - 1, x.y - 1);
    }
    int main() {
    	for (int i = 1; i <= 5; i++)for (int j = 1; j <= 5; j++)scanf("%d", mz[i] + j);
    	st = { 1,1 }, ed = { 5,5 };
    	queue<p>Q; Q.push(st); vis[st] = 1;
    
    	while (not Q.empty()) {
    		p tp = Q.front(); Q.pop();
    		
    		if (tp == ed) {
    			break;
    		}
    		for (int i = 0; i < 4; i++) {
    			int nx = tp.x + dx[i], ny = tp.y + dy[i];
    			p nxt = { nx,ny };
    
    			if (nx < 1 or nx > 5 or ny < 1 or ny > 5 or mz[nx][ny] == 1 or vis.count(nxt) == 1)continue;
    			vis[nxt] = 1;
    			pre[nxt] = tp;
    			Q.push(nxt);
    			//printf("%d %d
    ", nxt.x, nxt.y);
    		}
    	}
    	print(ed);
    }
    

    L - Oil Deposits

    用个并查集暴力就可以

    /*
     * @Author: zhl
     * @LastEditTime: 2020-12-22 17:57:53
     */
    #include<cstdio>
    #include<set>
    #define and &&
    #define or ||
    using namespace std;
    int n, m;
    
    char mp[200][200];
    int fa[20000];
    int find(int a) {
    	return a == fa[a] ? a : fa[a] = find(fa[a]);
    }
    void merge(int x, int y) {
    	x = find(x), y = find(y);
    	if (x != y)fa[x] = y;
    }
    int getid(int x, int y) {
    	return (x - 1) * m + y;
    }
    const int dx[] = { 1,1,0,-1,-1,-1,0,1 };
    const int dy[] = { 0,1,1,1,0,-1,-1,-1 };
    int main() {
    	while (scanf("%d%d", &n, &m) and n) {
    		for (int i = 1; i <= n; i++) {
    			scanf("%s", mp[i] + 1);
    		}
    
    		for (int i = 1; i <= n * m; i++)fa[i] = i;
    
    		for (int i = 1; i <= n; i++) {
    			for (int j = 1; j <= m; j++) {
    				for (int k = 0; k < 8; k++) {
    					int nx = i + dx[k], ny = j + dy[k];
    					if (mp[i][j] != '@' or nx < 1 or nx > n or ny < 1 or ny > m or mp[nx][ny] != '@')continue;
    					merge(getid(i, j), getid(nx, ny));
    				}
    			}
    		}
    		set<int>s;
    		for (int i = 1; i <= n; i++) {
    			for (int j = 1; j <= m; j++) {
    				if (mp[i][j] == '@')s.insert(find(getid(i, j)));
    			}
    		}
    		printf("%d
    ", s.size());
    	}
    }
    

    M - 非常可乐

    直接暴力

    /*
     * @Author: zhl
     * @LastEditTime: 2020-12-22 18:18:19
     */
    #include<cstdio>
    #include<queue>
    #include<map>
    #define min(a,b) (a<b?a:b)
    #define not !
    #define and &&
    #define or ||
    using namespace std;
    
    int S, N, M;
    typedef struct p {
    	int a, b, c;
    	p() {}
    	p(int _a, int _b, int _c) {
    		a = _a, b = _b, c = _c;
    	}
    	bool operator < (const p& rhs)const {
    		if (a != rhs.a)return a < rhs.a;
    		if (b != rhs.b)return b < rhs.b;
    		return c < rhs.c;
    	}
    }tup;
    map<tup, int>vis;
    bool ok(tup x) {
    	return (x.a == 0 and x.b == x.c) or (x.b == 0 and x.a == x.c) or (x.c == 0 and x.a == x.b);
    }
    
    tup res[6];
    void operate(tup x) {
    	int mx = min(N - x.b, x.a);
    	res[0] = tup(x.a - mx, x.b + mx, x.c);
    	mx = min(M - x.c, x.a);
    	res[1] = tup(x.a - mx, x.b, x.c + mx);
    	mx = min(S - x.a, x.b);
    	res[2] = tup(x.a + mx, x.b - mx, x.c);
    	mx = min(M - x.c, x.b);
    	res[3] = tup(x.a, x.b - mx, x.c + mx);
    	mx = min(S - x.a, x.c);
    	res[4] = tup(x.a + mx, x.b, x.c - mx);
    	mx = min(N - x.b, x.c);
    	res[5] = tup(x.a, x.b + mx, x.c - mx);
    }
    int main() {
    	while (scanf("%d%d%d", &S, &N, &M) and S != 0) {
    
    		queue<tup>Q; Q.push(p(S, 0, 0));
    		int ans = -1, now = 0;
    		vis.clear();
    		while (not Q.empty()) {
    			int sz = Q.size();
    			while (sz--) {
    				tup tp = Q.front(); Q.pop();
    				if (ok(tp)) {
    					ans = now;
    					break;
    				}
    				operate(tp);
    				for (int i = 0; i < 6; i++) {
    					if (vis.count(res[i]))continue;
    					Q.push(res[i]);
    					vis[res[i]] = 1;
    				}
    			}
    			if (ans != -1)break;
    			now++;
    		}
    		if (ans == -1)puts("NO");
    		else printf("%d
    ", ans);
    	}
    }
    
    /*
     * @Author: zhl
     * @LastEditTime: 2020-12-23 10:29:17
     */
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<bits/stdc++.h>
    using namespace std;
    #define min(a,b) (a < b ? a : b)
    int n, m;
    char mp[220][220];
    const int dx[] = { 1,0,-1,0 };
    const int dy[] = { 0,1,0,-1 };
    struct point {
    	int x, y;
    	point() {}
    	point(int _x, int _y) { x = _x, y = _y; }
    	bool operator < (const point& b)const {
    		if (x != b.x)return x < b.x;
    		return y < b.y;
    	}
    }stA,stB;
    int id(point x) {return (x.x - 1) * m + x.y;}
    int disA[50000], disB[50000], vis[50000];
    
    void bfs(point st,int* dis) {
    	memset(vis, 0, sizeof vis); vis[id(st)] = 1;
    	queue<point>Q;Q.push(st);
    	int now = 0;
    	while (not Q.empty()) {
    		int sz = Q.size();
    		while (sz--) {
    			point tp = Q.front(); Q.pop();
    			dis[id(tp)] = now;
    			for (int i = 0; i < 4; i++) {
    				point nxt = point(tp.x + dx[i], tp.y + dy[i]);
    				if (nxt.x < 1 or nxt.x > n or nxt.y < 1 or nxt.y > m or vis[id(nxt)])continue;
    				if (mp[nxt.x][nxt.y] == '#')continue;
    				vis[id(nxt)] = 1;
    				Q.push(nxt);
    			}
    		}
    		now++;
    	}
    }
    int main() {
    	while (~scanf("%d%d", &n, &m)) {
    		for (int i = 1; i <= n; i++) {
    			scanf("%s", mp[i] + 1);
    			for (int j = 1; j <= m; j++) {
    				if (mp[i][j] == 'M')stA = point(i, j);
    				if (mp[i][j] == 'Y')stB = point(i, j);
    			}
    		}
    		memset(disA, 0x3f, sizeof disA); memset(disB, 0x3f, sizeof disB);
    		bfs(stA, disA); bfs(stB, disB);
    		int ans = 0x3f3f3f3f;
    		for (int i = 1; i <= n; i++) {
    			for (int j = 1; j <= m; j++) {
    				if (mp[i][j] == '@') {
    					ans = min(ans, disA[id(point(i, j))] + disB[id(point(i, j))]);
    				}
    			}
    		}
    		printf("%d
    ", ans*11);
    	}
    }
    

    N - Find a way

    找一个点到两个点的距离和最小

    /*
     * @Author: zhl
     * @LastEditTime: 2020-12-23 10:29:17
     */
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<bits/stdc++.h>
    using namespace std;
    #define min(a,b) (a < b ? a : b)
    int n, m;
    char mp[220][220];
    const int dx[] = { 1,0,-1,0 };
    const int dy[] = { 0,1,0,-1 };
    struct point {
    	int x, y;
    	point() {}
    	point(int _x, int _y) { x = _x, y = _y; }
    	bool operator < (const point& b)const {
    		if (x != b.x)return x < b.x;
    		return y < b.y;
    	}
    }stA,stB;
    int id(point x) {return (x.x - 1) * m + x.y;}
    int disA[50000], disB[50000], vis[50000];
    
    void bfs(point st,int* dis) {
    	memset(vis, 0, sizeof vis); vis[id(st)] = 1;
    	queue<point>Q;Q.push(st);
    	int now = 0;
    	while (not Q.empty()) {
    		int sz = Q.size();
    		while (sz--) {
    			point tp = Q.front(); Q.pop();
    			dis[id(tp)] = now;
    			for (int i = 0; i < 4; i++) {
    				point nxt = point(tp.x + dx[i], tp.y + dy[i]);
    				if (nxt.x < 1 or nxt.x > n or nxt.y < 1 or nxt.y > m or vis[id(nxt)])continue;
    				if (mp[nxt.x][nxt.y] == '#')continue;
    				vis[id(nxt)] = 1;
    				Q.push(nxt);
    			}
    		}
    		now++;
    	}
    }
    int main() {
    	while (~scanf("%d%d", &n, &m)) {
    		for (int i = 1; i <= n; i++) {
    			scanf("%s", mp[i] + 1);
    			for (int j = 1; j <= m; j++) {
    				if (mp[i][j] == 'M')stA = point(i, j);
    				if (mp[i][j] == 'Y')stB = point(i, j);
    			}
    		}
    		memset(disA, 0x3f, sizeof disA); memset(disB, 0x3f, sizeof disB);
    		bfs(stA, disA); bfs(stB, disB);
    		int ans = 0x3f3f3f3f;
    		for (int i = 1; i <= n; i++) {
    			for (int j = 1; j <= m; j++) {
    				if (mp[i][j] == '@') {
    					ans = min(ans, disA[id(point(i, j))] + disB[id(point(i, j))]);
    				}
    			}
    		}
    		printf("%d
    ", ans*11);
    	}
    }
    
  • 相关阅读:
    第二章例2-11
    第二章例2-10
    例2-11
    例2-9+2-10
    例2-7+例2-8
    例2-5+2-6
    例2-4
    例2-3
    例2-2
    例2-1
  • 原文地址:https://www.cnblogs.com/sduwh/p/14177614.html
Copyright © 2011-2022 走看看