双十中学2020 暑假模拟测试 Round #4(div 2)全题解

灌溉(irrigation)

思路——最小生成树

一看这题目,明显的最小生成树模板题。
给每两个点之间建边,边权是它们的欧氏距离,当欧式距离 < C的时候边权为无穷大,然后直接上Prim模板就行了。因为我只会写Prim

代码

#include <bits/stdc++.h>
#define ri register int 
using namespace std;
const int INF = 2147483647;
const int maxn = 2e3 + 7;
int n,c,x[maxn],y[maxn],mmin,u,ans;
int g[maxn][maxn],d[maxn],vis[maxn];
inline int sqr(const int &x) {
	return x * x;
}
int main() {
	scanf("%d%d",&n,&c);
	for(int i = 1;i <= n;++ i) {
		scanf("%d%d",&x[i],&y[i]); 
	}
	for(ri i = 1;i <= n;++ i) {	//建边
		for(ri j = 1;j <= n;++ j) {
			ri t = sqr(x[i] - x[j]) + sqr(y[i] - y[j]);
			g[i][j] = (t < c ? INF : t);
		}
	}
	//以下是Prim算法
	memset(vis,true,sizeof(vis));
	vis[1] = false;
	for(ri i = 1;i <= n;++ i) {
		d[i] = g[1][i]; 
	}
	for(ri i = 1;i < n;++ i) {
		mmin = INF,u = 0;
		for(ri j = 1;j <= n;++ j) {
			if(d[j] < mmin && vis[j]) {
				mmin = d[j],
				u = j; 
			}
		}
		if(mmin == INF) {
			printf("-1");
			return 0;
		}
		ans += mmin;
		vis[u] = 0;
		for(ri j = 1;j <= n;++ j) {
			if(vis[j] && g[u][j] < d[j]) {
				d[j] = g[u][j]; 
			}
		}
	}
	//不会有人认为以下也是Prim算法吧。。。。。。
	printf("%d\n",ans);
	return 0;
}

懒惰的奶牛(lazy) 魔改版本

解题思路——前缀和

原题也是用的前缀和 原题题解我还没写
虽然被魔改后加了一维,但也丝毫不影响我用前缀和。
我们对每一行做一个前缀和,然后枚举每个位置。
假如那个位置的坐标是(i,j),储存前缀和的数组为b;
那么这个位置能吃到的牧草的数量就是:
∑ l i n e = i − k i + k b [ l i n e ] [ j + k − ∣ i − l i n e ∣ ] − b [ l i n e ] [ i − k + ∣ i − l i n e ∣ ] \sum_{line=i-k}^{i+k}b[line][j+k-|i - line|] - b[line][i-k+|i - line|] line=iki+kb[line][j+kiline]b[line][ik+iline]
求出每个位置能吃到的牧草,然后取其中的最大值就能得出答案。

答案

#include <bits/stdc++.h>
#define ri register int
using namespace std;
const int maxn = 407;
int n,k,a[maxn][maxn],b[maxn][maxn];
int up,down,s,l,r,sum,ans;
int main() {
	scanf("%d%d",&n,&k);
	for(ri i = 1;i <= n;++ i) {
		for(ri j = 1;j <= n;++ j) {
			scanf("%d",&a[i][j]); 
			b[i][j] = b[i][j - 1] + a[i][j];
		}
	}
	for(ri i = 1;i <= n;++ i) {
		for(ri j = 1;j <= n;++ j) {
			up = i + k,down = i - k,sum = 0;
			if(up > n)		up = n;
			if(down < 1)	down = 1;
			for(ri li = down;li <= up;++ li) {
				s = abs(i - li);
				l = max(j - k + s,1);
				r = min(j + k - s,n);
				sum += b[li][r] - b[li][l - 1];
			}
			ans = max(ans,sum);
		}
	}
	printf("%d\n",ans);
	return 0;
}

哞哞(mooomoo)

解题思路——背包

看题目描述就有背包的影子,果断抄起背包 就打 就写
水题没什么好说的,要是搞不懂那就看代码

代码

#include <bits/stdc++.h>
using namespace std;
const int maxs = 1e6 + 7;
const int maxn = 107;
const int maxm = 27;
int f[maxs];
int a[maxn],b[maxn],v[maxm];
int n,m,ms;
int main() {
	scanf("%d%d",&n,&m); 
	for(int i = 1;i <= m;++ i) {
		scanf("%d",&v[i]);
	}
	for(int i = 1;i <= n;++ i) {
		scanf("%d",&a[i]);
	}
	for(int i = 1;i <= n;++ i) {
		b[i] = a[i] - (max(a[i - 1] - 1,0));
		ms = max(ms,b[i]);
	}
	memset(f,0x3f,sizeof(f));
	f[0] = 0;
	for(int i = 1;i <= m;++ i) {	//背包
		for(int j = v[i];j <= ms;++ j) {
			f[j] = min(f[j],f[j - v[i]] + 1);
		}
	}
	int ans = 0;
	for(int i = 1;i <= n;i ++) {
		if(f[b[i]] == 0x3f3f3f3f) {
			printf("-1\n");
			return 0;
		}
		ans += f[b[i]];
	}
	printf("%d\n",ans);
}
}

奶牛选美大赛(beauty)

解题思路——DFS + 魔改Floyd

三个块相连有两种方式:
方式1
三个块直接相连,比如:
块1连块2,块2连块3;
块1连块3,块2连块3;
块1连块3,块1连块2;
方式2
三个块都连在某一个点上

算法大致

输入 O(n2)

首先先用DFS标记出每一个块 O(2n2)

所以我们要求出每一个点到每一个块的最短距离 O(n4)

接着求出相连方式1的最短值 O(n2)

最后利用魔改Floyd求出相连方式2的最短值 O(n2)

总时间 O(n4+5n2) n ≤ 50 n \leq 50 n50 完全够用

#include <bits/stdc++.h>
using namespace std;
const int maxn = 57;
const int dx[4] = {0,0,1,-1};
const int dy[4] = {1,-1,0,0}; 
bool vis[maxn][maxn];
char s[maxn][maxn];
int n,m,cnt,p[maxn][maxn];
int dis[4][maxn][maxn]; 
int f[maxn][maxn];
inline void dfs(int x,int y) {
	if(vis[x][y]) {
		return ;
	}
	if(s[x][y] == 'X') {
		vis[x][y] = 1;
		p[x][y] = cnt;
		for(int i = 0;i < 4;++ i) {
			dfs(x + dx[i],y + dy[i]);
		} 
	}
}
inline void distance(int x,int y,int id) {
	for(int i = 1;i <= n;++ i){
		for(int j = 1;j <= m;++ j) {
			dis[id][i][j] = min(dis[id][i][j],abs(x - i) + abs(y - j));
		} 
	}
}
int main() {
	memset(dis,0x3f,sizeof(dis));
	memset(f,0x3f,sizeof(f)); 
	scanf("%d%d",&n,&m); 
	for(int i = 1;i <= n;++ i) {
		scanf("%s",s[i] + 1);
	}
	for(int i = 1;i <= n;++ i) {
		for(int j = 1;j <= m;++ j) {
			if(!vis[i][j] && s[i][j] == 'X') {
				++ cnt;
				dfs(i,j);
			} 
		} 
	}
	for(int i = 1;i <= n;++ i) {
		for(int j = 1;j <= m;++ j) {
			if(p[i][j] != 0) {
				distance(i,j,p[i][j]);
			}
		}
	}
	for(int i = 1;i <= n;++ i) {
		for(int j = 1;j <= m;++ j) {
			if(p[i][j] != 0) {
				f[p[i][j]][1] = f[1][p[i][j]] = min(f[1][p[i][j]],dis[1][i][j]);
				f[p[i][j]][2] = f[2][p[i][j]] = min(f[2][p[i][j]],dis[2][i][j]);
				f[p[i][j]][3] = f[3][p[i][j]] = min(f[3][p[i][j]],dis[3][i][j]);
			}	
		}
	}
	int ans = min(f[1][2] + f[2][3],min(f[1][3] + f[2][3],f[1][2] + f[1][3]));
	for(int i = 1;i <= n;++ i) {
		for(int j = 1;j <= m;++ j) {
			ans = min(ans,dis[1][i][j] + dis[2][i][j] + dis[3][i][j]);
		}
	}
	cout << ans - 2; 
	return 0;
}

如果以上代码或思路上有什么问题的欢迎在评论区指出 本蒟蒻保证不了能否回答

*ps:
此题解是本人闲的无聊才写的 写题解真累
至于Round #1 #2 #3……以后有时间再写吧……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
抱歉,根据提供的引用内容,我无法理解你具体想要问什么问题。请提供更清晰明确的问题,我将竭诚为你解答。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Codeforces Round 860 (Div. 2)题解](https://blog.csdn.net/qq_60653991/article/details/129802687)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [【Codeforces】 Codeforces Round 865 (Div. 2) (补赛)](https://blog.csdn.net/t_mod/article/details/130104033)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Codeforces Round 872 (Div. 2)(前三道](https://blog.csdn.net/qq_68286180/article/details/130570952)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值