简单搜索 + 贪心


  这周日的白天没什么事可做,花一天的时间做下新生第二轮考核里边的简单搜索专题,复习一下基础的bfs和dfs,练练手,前几天也做几道贪心练下思维(最近思维题做得比较少,脑子有点短路了…)。

简单搜索:

A - Red and Black (HDU - 1312)

在这里插入图片描述
  这道题是要我们找跟’@’同属一个连通块的’.’个数,所以直接搜索找符合条件的数量就可以了,统计过的标记下即可(水题)。
具体的实现代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
 
void debug_out(){
    cerr << endl;
}
template<typename Head, typename... Tail>
void debug_out(Head H, Tail... T){
    cerr << " " << to_string(H);
    debug_out(T...);
}
#ifdef local
#define debug(...) cerr<<"["<<#__VA_ARGS__<<"]:",debug_out(__VA_ARGS__)
#else
#define debug(...) 55
#endif
int n, m, s[25][25], vis[25][25], a[4] = {0, 0, 1, -1}, b[4] = {1, -1, 0, 0}; 
char u[25][25];
int bfs(int p, int q){
	if(vis[p][q]) return 0;
	vis[p][q] = 1;
	int ans = 1;
	for(int i = 0; i < 4; i++){
		int x = p + a[i], y = q + b[i];
		if(u[x][y] == '.' && x >= 0 && y >= 0 && x < n && y < m){
			ans += bfs(x, y);
			vis[x][y] = 1;
		}
	}
	return ans;
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int p, q;
	while(cin >> m >> n){
		if(m == 0 && n == 0) break;
		memset(s, 0, sizeof s);
		memset(vis, 0, sizeof vis); 
		for(int i = 0; i < n; i++){
			for(int j = 0; j < m; j++){
				cin >> u[i][j];
				if(u[i][j] == '@'){
					p = i, q = j;
				} 
			}
		}
		cout << bfs(p, q) << endl;
	} 
    return 0;
}

B - Knight Moves (HDU - 1372)

在这里插入图片描述
  这道题是8 * 8的棋盘上的两个点,找到从一个点到另一个点的最短操作次数,每次操作只能进行象棋里“马”能走的操作,典型的宽搜(水题)。
具体的实现代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
 
void debug_out(){
    cerr << endl;
}
template<typename Head, typename... Tail>
void debug_out(Head H, Tail... T){
    cerr << " " << to_string(H);
    debug_out(T...);
}
#ifdef local
#define debug(...) cerr<<"["<<#__VA_ARGS__<<"]:",debug_out(__VA_ARGS__)
#else
#define debug(...) 55
#endif
char w[5], v[5];
int s, vis[10][10];
int a[8] = {1, 1, 2, 2, -1, -1, -2, -2}, b[8] = {2, -2, 1, -1, 2, -2, 1, -1};
struct node{
	int x, y, s;
};
int bfs(){
	memset(vis, 0, sizeof vis);
	queue<node> q;
	node p;
	p.x = w[0] - 'a', p.y = w[1] - '1', p.s = 0;
	vis[p.x][p.y] = 1;
	int ex = v[0] - 'a', ey = v[1] - '1';
	if(p.x == ex && p.y == ey) return p.s;
	q.push(p);
	while(!q.empty()){
		node u = q.front();
		q.pop();
		for(int i = 0; i < 8; i++){
			node t;
			t.x = u.x + a[i], t.y = u.y + b[i];
			if(t.x == ex && t.y == ey) return u.s + 1;
			if(t.x >= 0 && t.y >= 0 && t.x < 8 && t.y < 8 && vis[t.x][t.y] == 0){
				t.s = u.s + 1;
				vis[t.x][t.y] = 1;
				q.push(t);
			}
		}
	}
	return 0;
}
int main(){
//    ios::sync_with_stdio(false);
//    cin.tie(0), cout.tie(0);
    while(~scanf("%s%s", w, v)){
    	printf("To get from %s to %s takes %d knight moves.\n", w, v, bfs());
	}
    return 0;
}

C - Oil Deposits (HDU - 1241)

在这里插入图片描述
  找总共有多少个连通块,斜着也算是一个连通块,直接搜索,满足题意的坐标且已被搜索过的点要变成’*’,最后把不同连通块的个数累加在一起即可。
具体的实现代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
 
void debug_out(){
    cerr << endl;
}
template<typename Head, typename... Tail>
void debug_out(Head H, Tail... T){
    cerr << " " << to_string(H);
    debug_out(T...);
}
#ifdef local
#define debug(...) cerr<<"["<<#__VA_ARGS__<<"]:",debug_out(__VA_ARGS__)
#else
#define debug(...) 55
#endif
char u[105][105];
int n, m, a[8] = {0, 0, -1, -1, -1, 1, 1, 1}, b[8] = {-1, 1, -1, 0, 1, 0, -1, 1};
void bfs(int p, int q){
	u[p][q] = '*';
	for(int i = 0; i < 8; i++){
		int x = p + a[i], y = q + b[i];
		if(x >= 0 && y >= 0 && x < n && y < m && u[x][y] == '@') bfs(x, y);
	}
	return;
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    while(cin >> n >> m){
    	int ans = 0;
    	if(n == 0 && m == 0) break;
    	for(int i = 0; i < n; i++){
    		for(int j = 0; j < m; j++){
    			cin >> u[i][j];
			}
		}
		for(int i = 0; i < n; i++){
			for(int j = 0; j < m; j++){
				if(u[i][j] == '@'){
					bfs(i, j);
					ans++;
				}
			}
		}
		cout << ans << '\n';
	}
    return 0;
}

D - Rescue (HDU - 1242)

在这里插入图片描述
  其实这道题我走了弯路,用dfs做比用bfs做简单,因为dfs只要一直搜索,然后记录到达目的坐标的最小值即可。而bfs要用优先队列做,因为每遇到’x’,走一步的代价是2,所以从一个点到另一点扩充的时候,如果是普通的队列,早入队的节点中s(操作的代价)不一定比晚入队的节点中s(操作的代价)少,所以要维护一个优先队列,才能保证最后返回的是两个点之间操作的最小代价。因为是多组输入,所以在处理每组数据调用bfs函数的时候要把优先队列的元素(上一组数据得到的)都弹出。
具体的实现代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
 
void debug_out(){
    cerr << endl;
}
template<typename Head, typename... Tail>
void debug_out(Head H, Tail... T){
    cerr << " " << to_string(H);
    debug_out(T...);
}
#ifdef local
#define debug(...) cerr<<"["<<#__VA_ARGS__<<"]:",debug_out(__VA_ARGS__)
#else
#define debug(...) 55
#endif
#define INF 0x3f3f3f3f
int n, m, sx, sy, ex, ey, ans, vis[205][205], a[4] = {0, 0, -1, 1}, b[4] = {1, -1, 0, 0};
char u[205][205];
struct node{
	int x, y, s;
};
priority_queue<node> q;
bool operator<(const node a, const node b){
	return a.s > b.s;
}
int bfs(int x, int y){
	while(!q.empty()) q.pop();
	node p;
	p.x = x, p.y = y, p.s = 0;
	q.push(p);
	while(!q.empty()){
		node t = q.top();
		q.pop();
		for(int i = 0; i < 4; i++){
			node v;
			v.x = t.x + a[i], v.y = t.y + b[i], v.s = t.s + 1;
			if(v.x == ex && v.y == ey) return v.s;
			if(v.x >= 0 && v.y >= 0 && v.x < n && v.y < m && (u[v.x][v.y] == '.' || u[v.x][v.y] == 'x') && vis[v.x][v.y] == 0){
				if(u[v.x][v.y] == 'x') v.s++;
				q.push(v);
				vis[v.x][v.y] = 1;
			} 
		}
	}
	return INF; 
} 
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    while(cin >> n >> m){
    	memset(vis, 0, sizeof vis);
	    for(int i = 0; i < n; i++){
	    	for(int j = 0; j < m; j++){
	    		cin >> u[i][j];
				if(u[i][j] == 'r') sx = i, sy = j;
				else if(u[i][j] == 'a') ex = i, ey = j;
			}
		}
		debug(sx, sy);
		debug(ex, ey);
		ans = bfs(sx, sy);
		if(ans == INF) cout << "Poor ANGEL has to stay in the prison all his life.\n";
		else cout << ans << '\n';	
	}
    return 0;
}

E - 迷宫问题 (POJ - 3984)

在这里插入图片描述
  这道题也是经典的搜索版题,要注意确定到达某个点的最短操作次数的时候,把它前面的点记录下来,最后递归输出这些点的坐标即可。
具体的实现代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <string>
#include <cstring>
#include <map>
#include <queue>
using namespace std;
typedef long long LL;
 
void debug_out(){
    cerr << endl;
}
template<typename Head, typename... Tail>
void debug_out(Head H, Tail... T){
    cerr << " " << to_string(H);
    debug_out(T...);
}
#ifdef local
#define debug(...) cerr<<"["<<#__VA_ARGS__<<"]:",debug_out(__VA_ARGS__)
#else
#define debug(...) 55
#endif
#define INF 0x3f3f3f3f
int u[5][5], prex[5][5], prey[5][5], ans[5][5], a[4] = {0, 0, 1, -1}, b[4] = {1, -1, 0, 0};
int n = 5, m = 5
void bfs(int p, int q){
	for(int i = 0; i < 4; i++){
		int x = p + a[i], y = q + b[i];
		if(x >= 0 && y >= 0 && x < n && y < m && u[x][y] == 0){
			if((ans[p][q] + 1) < ans[x][y]){
				ans[x][y] = ans[p][q] + 1;
				prex[x][y] = p, prey[x][y] = q;
				bfs(x, y);
			}
		}
	}
	return;
}
void print(int x, int y){
	if(x == 0 && y == 0){
		cout << "(0, 0)\n"; 
		return;
	}
	print(prex[x][y], prey[x][y]);
	cout << "(" << x << "," << " " << y << ")\n";
	
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
	for(int i = 0; i < 5; i++){
		for(int j = 0; j < 5; j++){
			cin >> u[i][j];
		}
	}
	memset(ans, INF, sizeof ans);
	ans[0][0] = 0;
	bfs(0, 0);
	print(4, 4);
    return 0;
}

F - 棋盘问题 (POJ - 1321)

在这里插入图片描述
  直接深搜记录前i行哪些列有棋子,如果把所有棋子都摆好了,则可行方案数加一,之后回溯,注意每次dfs的时候,要传入参数,表示前r行已经排好了,接下来将从第r + 1行开始放棋子。
具体的实现代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <string>
#include <cstring>
#include <map>
#include <queue>
using namespace std;
typedef long long LL;
 
void debug_out(){
    cerr << endl;
}
template<typename Head, typename... Tail>
void debug_out(Head H, Tail... T){
    cerr << " " << to_string(H);
    debug_out(T...);
}
#ifdef local
#define debug(...) cerr<<"["<<#__VA_ARGS__<<"]:",debug_out(__VA_ARGS__)
#else
#define debug(...) 55
#endif
int n, k, ans;
char u[10][10];
int y[10];
void dfs(int t, int r){
	if(t == k){
		ans++;
		return;
	}
	for(int i = r + 1; i < n; i++){
		for(int j = 0; j < n; j++){
			if(u[i][j] == '#' && !y[j]){
				y[j]++, t++;
				dfs(t, i);
				y[j]--, t--;
			} 
		} 
	}
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
	while(cin >> n >> k){
		ans = 0;
		if(n == -1) break;
		memset(y, 0, sizeof y);
		for(int i = 0; i < n; i++){
			for(int j = 0; j < n; j++){
				cin >> u[i][j];
			}
		}
		dfs(0, -1);
		cout << ans << '\n'; 	
	}
    return 0;
}

G - Find The Multiple (POJ - 1426)

在这里插入图片描述
  这道题需要用到dfs来解决,而且这道题的测试数据得到的倍数的位数恰好不超过20,正好符合long long的数据范围,所以直接定一个long long类型的整数记录数据即可,若m是n的倍数,则直接返回并输出m。调用dfs函数时,如果遇到m是n的倍数,要把标记为1,题目要求只要一个倍数即可,所以dfs函数中当标记为1时,不断return。
具体的实现代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <string>
#include <cstring>
#include <map>
#include <queue>
using namespace std;
typedef long long LL;
 
void debug_out(){
    cerr << endl;
}
template<typename Head, typename... Tail>
void debug_out(Head H, Tail... T){
    cerr << " " << to_string(H);
    debug_out(T...);
}
#ifdef local
#define debug(...) cerr<<"["<<#__VA_ARGS__<<"]:",debug_out(__VA_ARGS__)
#else
#define debug(...) 55
#endif
int n, flag;
void dfs(LL m, int n, int s){
	if(flag ||s == 20) return;
	if(m % n == 0){
		flag = 1;
		cout << m << endl;
		return;
	}
	dfs(m * 10 + 1, n, s + 1);
	dfs(m * 10, n, s + 1);
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    while(cin >> n){
    	if(n == 0) break;
    	flag = 0;
    	dfs(1, n, 1);
	}
    return 0;
}

H - 统计问题 (HDU - 2563)

在这里插入图片描述
  没啥好讲的,直接递推…
具体的实现代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <string>
#include <cstring>
#include <map>
#include <queue>
using namespace std;
typedef long long LL;
 
void debug_out(){
    cerr << endl;
}
template<typename Head, typename... Tail>
void debug_out(Head H, Tail... T){
    cerr << " " << to_string(H);
    debug_out(T...);
}
#ifdef local
#define debug(...) cerr<<"["<<#__VA_ARGS__<<"]:",debug_out(__VA_ARGS__)
#else
#define debug(...) 55
#endif
int dp[25];
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
	dp[1] = 3;
	dp[2] = 7;
	for(int i = 3; i <= 20; i++){
		dp[i] = dp[i - 1] * 2 + dp[i - 2];
	}
	int t, n;
	cin >> t;
	while(t--){
		cin >> n;
		cout << dp[n] << endl; 
	}
    return 0;
}

I - LETTERS (POJ - 1154)

在这里插入图片描述
  这道题用dfs做,重点是记录到达某个点的时候,前面经过的点里的字母有什么,所以要用一个vis数组保存以A ~ Z为下标的字母是否已经走过了,每次更新经过字母数量的最大值,直到“无路可走”就回溯。
具体的实现代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <string>
#include <cstring>
#include <map>
#include <queue>
using namespace std;
typedef long long LL;
 
void debug_out(){
    cerr << endl;
}
template<typename Head, typename... Tail>
void debug_out(Head H, Tail... T){
    cerr << " " << to_string(H);
    debug_out(T...);
}
#ifdef local
#define debug(...) cerr<<"["<<#__VA_ARGS__<<"]:",debug_out(__VA_ARGS__)
#else
#define debug(...) 55
#endif
char o[25][25];
int ans, vis[30], u[25][25], a[4] = {0, 0, 1, -1}, b[4] = {1 , -1, 0, 0};
int n, m;
void dfs(int p, int q, int s){
	ans = max(ans, s);
	vis[u[p][q]]++;
	for(int i = 0; i < 4; i++){
		int x = p + a[i], y = q + b[i];
		if(x >= 0 && y >= 0 && x < n && y < m && !vis[u[x][y]]){
			dfs(x, y, s + 1);
			vis[u[x][y]]--;
		}
	}
}
int main(){
//    ios::sync_with_stdio(false);
//    cin.tie(0), cout.tie(0);
    while(cin >> n >> m){
    	ans = 0;
    	for(int i = 0; i < n; i++){
	    	for(int j = 0; j < m; j++){
	    		cin >> o[i][j];
	    		u[i][j] = o[i][j] - 'A';
	    		debug(o[i][j]); 
			}
		}
		dfs(0, 0, 1);
		cout << ans << '\n';
	}
    return 0;
}

J - N皇后问题 (HDU - 2553)

在这里插入图片描述
  经典的dfs算法,主要是用加减法表示两个棋子是否在同一个对角线上…
具体的实现代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
 
void debug_out(){
    cerr << endl;
}
template<typename Head, typename... Tail>
void debug_out(Head H, Tail... T){
    cerr << " " << to_string(H);
    debug_out(T...);
}
#ifdef local
#define debug(...) cerr<<"["<<#__VA_ARGS__<<"]:",debug_out(__VA_ARGS__)
#else
#define debug(...) 55
#endif
int n, ans, cnt,flag, s[15], u[15];
void dfs(int cnt){
	if(cnt == n){
		ans++;
		return;
	}
	for(int i = 0; i < n; i++){
		u[cnt] = i;
		flag = 1;
		for(int j = 0; j < cnt; j++){
			if(i == u[j] || u[cnt] + cnt == u[j] + j || u[cnt] - cnt == u[j] - j){
				flag = 0;
				break;
			}
		}
		if(flag) dfs(cnt + 1);
	}
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    for(int i = 1; i <= 10; i++){
    	n = i;
    	ans = 0;
    	dfs(0);
    	s[i] = ans;
    	debug(i, s[i]);
	}
	while(cin >> n){
		if(!n) break;
		cout << s[n] << '\n'; 
	}
    return 0;
}

贪心:

AcWing 905. 区间选点


  经典的区间选点问题,每个区间按照右端点从小到大进行排序,先选第一个区间的右端点为第一个点,不断遍历后面的区间,如果遇到某个区间的左端点在这个点的右边,则再选这个区间的右端点为新的点,这样循环下去即得最终答案。
具体的实现代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
 
void debug_out(){
    cerr << endl;
}
template<typename Head, typename... Tail>
void debug_out(Head H, Tail... T){
    cerr << " " << to_string(H);
    debug_out(T...);
}
#ifdef local
#define debug(...) cerr<<"["<<#__VA_ARGS__<<"]:",debug_out(__VA_ARGS__)
#else
#define debug(...) 55
#endif
const int N = 100005;
struct node{
	int l, r;
	bool operator < (const node & A) const{
		return r < A.r;
	}
}u[N];
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
	int n;
	cin >> n; 
	for(int i = 0; i < n; i++){
		cin >> u[i].l >> u[i].r;
	}
	sort(u, u + n);
	int ans = 0, ed = -2e9;
	for(int i = 0; i < n; i++){
		if(u[i].l > ed){
			ans++;
			ed = u[i].r;
		}
	}
	cout << ans; 
    return 0;
}

AcWing 908. 最大不相交区间数量

在这里插入图片描述
  这道题的代码跟上道题一模一样,上一道题选的点所在的区间就是这道题所选的区间。
具体的实现代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
 
void debug_out(){
    cerr << endl;
}
template<typename Head, typename... Tail>
void debug_out(Head H, Tail... T){
    cerr << " " << to_string(H);
    debug_out(T...);
}
#ifdef local
#define debug(...) cerr<<"["<<#__VA_ARGS__<<"]:",debug_out(__VA_ARGS__)
#else
#define debug(...) 55
#endif
const int N = 100005;
struct node{
	int l, r;
	bool operator < (const node & A) const{
		return r < A.r;
	}
}u[N];
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
	int n;
	cin >> n; 
	for(int i = 0; i < n; i++){
		cin >> u[i].l >> u[i].r;
	}
	sort(u, u + n);
	int ans = 0, ed = -2e9;
	for(int i = 0; i < n; i++){
		if(u[i].l > ed){
			ans++;
			ed = u[i].r;
		}
	}
	cout << ans; 
    return 0;
}

AcWing 906. 区间分组

在这里插入图片描述
  贪心决策:从前往后枚举每个区间,判断此区间能否将其放到现有的组中,如果一个区间的左端点比最小组的右端点要小,u[i].l <= c.top(),就开一个新组c.push(u[i].r);
  如果一个区间的左端点比最小组的右端点要大,则放在该组,c.pop(), c.push(u[i].r);
  每组去除右端点最小的区间,只保留一个右端点较大的区间,这样c有多少区间,就有多少组。(c是一个小根堆,维护的是每个组所有区间最右端点的最小值)
具体的实现代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
 
void debug_out(){
    cerr << endl;
}
template<typename Head, typename... Tail>
void debug_out(Head H, Tail... T){
    cerr << " " << to_string(H);
    debug_out(T...);
}
#ifdef local
#define debug(...) cerr<<"["<<#__VA_ARGS__<<"]:",debug_out(__VA_ARGS__)
#else
#define debug(...) 55
#endif
const int N = 100005;
struct node{
	int l, r;
	bool operator < (const node & A) const{
		return l < A.l;
	}
}u[N];
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	for(int i = 0; i < n; i++){
		int l, r;
		cin >> l >> r;
		u[i] = {l, r};
	}
	sort(u, u + n);
	priority_queue<int, vector<int>, greater<int> > c;
	for(int i = 0; i < n; i++){
		if(c.empty() || c.top() >= u[i].l) c.push(u[i].r);
		else{
			c.pop();
			c.push(u[i].r);
		}
	}
	cout << c.size();
    return 0;
}

AcWing 907. 区间覆盖

在这里插入图片描述
在这里插入图片描述
具体的实现代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
 
void debug_out(){
    cerr << endl;
}
template<typename Head, typename... Tail>
void debug_out(Head H, Tail... T){
    cerr << " " << to_string(H);
    debug_out(T...);
}
#ifdef local
#define debug(...) cerr<<"["<<#__VA_ARGS__<<"]:",debug_out(__VA_ARGS__)
#else
#define debug(...) 55
#endif
const int N = 100005;
struct node{
	int l, r;
	bool operator < (const node & A) const{
		return l < A.l;
	}
}u[N];
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
	int n;
	int st, ed;
	cin >> st >> ed;
	cin >> n;
	for(int i = 0; i < n; i++){
		int l, r;
		cin >> l >> r;
		u[i] = {l, r};
	} 
	sort(u, u + n);
	int flag = 0, ans = 0;
	for(int i = 0; i < n; i++){
		int r = -2e9, j = i;
		while(j < n && u[j].l <= st){
			r = max(r, u[j].r);
			j++;
		}
		if(r == -2e9) break;
		ans++;
		if(r >= ed){
			flag = 1;
			break;
		}
		st = r;
		j = i - 1;	
	}
	if(!flag) cout << "-1";
	else cout << ans;
    return 0;
}

AcWing 148. 合并果子

在这里插入图片描述
  经典哈夫曼树的模型,每次合并重量最小的两堆果子即可。
  时间复杂度:使用小根堆维护所有果子,每次弹出堆顶的两堆果子,并将其合并,合并之后将两堆重量之和再次插入小根堆中。每次操作会将果子的堆数减一,一共操作n - 1次即可将所有果子合并成1堆。每次操作涉及到2次堆的删除操作和1次堆的插入操作,计算量是O(logn),因此总时间复杂度是O(nlogn)。
具体的实现代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
 
void debug_out(){
    cerr << endl;
}
template<typename Head, typename... Tail>
void debug_out(Head H, Tail... T){
    cerr << " " << to_string(H);
    debug_out(T...);
}
#ifdef local
#define debug(...) cerr<<"["<<#__VA_ARGS__<<"]:",debug_out(__VA_ARGS__)
#else
#define debug(...) 55
#endif
const int N = 100005;
int ans;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
	priority_queue<int, vector<int>, greater<int>> u;
	int n;
	cin >> n;
	for(int i = 0; i < n; i++){
		int x;
		cin >> x;
		u.push(x);
	}
	while(u.size() > 1){
		int a = u.top();
		u.pop();
		int b = u.top();
		u.pop();
		u.push(a + b);
		ans += a + b;
	}
	cout << ans; 
    return 0;
}

AcWing 913. 排队打水.

在这里插入图片描述
水题…
具体的实现代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
 
void debug_out(){
    cerr << endl;
}
template<typename Head, typename... Tail>
void debug_out(Head H, Tail... T){
    cerr << " " << to_string(H);
    debug_out(T...);
}
#ifdef local
#define debug(...) cerr<<"["<<#__VA_ARGS__<<"]:",debug_out(__VA_ARGS__)
#else
#define debug(...) 55
#endif
const int N = 100005;
int a[N];
LL ans;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
	int n;
	cin >> n; 
	for(int i = 0; i < n ; i++){
		cin >> a[i];	
	}
	sort(a, a + n);
	for(int i = 0; i < n; i++){
		ans += a[i] * (n - i - 1);
	}
	cout << ans; 
    return 0;
}

AcWing 104. 货仓选址

在这里插入图片描述
  把货仓建在中位数的位置,它能保证左右有对应的两点到这个位置的距离和最小,是这两个点的局部最优解,所有点两两一组都有局部最优解,合起来就是全局最优解,所以货仓建在中位数的位置能保证总距离和最小。
具体的实现代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
 
void debug_out(){
    cerr << endl;
}
template<typename Head, typename... Tail>
void debug_out(Head H, Tail... T){
    cerr << " " << to_string(H);
    debug_out(T...);
}
#ifdef local
#define debug(...) cerr<<"["<<#__VA_ARGS__<<"]:",debug_out(__VA_ARGS__)
#else
#define debug(...) 55
#endif
const int N = 100005;
int a[N];
LL ans;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
	int n; 
	cin >> n;
	for(int i = 0; i < n; i++){
		cin >>a[i];
	}
	sort(a, a + n);
	for(int i = 0; i < n; i++){
		ans += abs(a[i] - a[n / 2]);
	}
	cout << ans;
    return 0;
}

AcWing 125. 耍杂技的牛

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
具体的实现代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
 
void debug_out(){
    cerr << endl;
}
template<typename Head, typename... Tail>
void debug_out(Head H, Tail... T){
    cerr << " " << to_string(H);
    debug_out(T...);
}
#ifdef local
#define debug(...) cerr<<"["<<#__VA_ARGS__<<"]:",debug_out(__VA_ARGS__)
#else
#define debug(...) 55
#endif
const int N = 50005;
struct node{
	int w, s;
	bool operator < (const node & A) const{
		return w + s < A.w + A.s;
	}
}u[50005];
LL ans = -2e9, sum;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	for(int i = 0; i < n; i++){
		int w, s;
		cin >> w >> s;
		u[i].w = w;
		u[i].s = s;
	}
	sort(u, u + n);
	for(int i = 0; i < n; i++){
		ans = max(ans, sum - u[i].s);
		sum += u[i].w;
	} 
	cout << ans;
    return 0;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值