【G - Supermarket】

本文探讨了贪心算法在物品出售问题中的应用,通过将物品按价值排序并尽可能延后出售时间来最大化收益。同时,引入并查集进行优化,减少查找空闲位置的复杂度,实现更高效的解决方案。

思路:

  • 贪心(可加并查集优化)

  • 贪心:

    1. 选取方法:先将物品按价值从高到低排序,尽量把出售物品的时间向后放,不要影响前面的物品。
      拿最高价物品A来说:
      1. 有没有可能不选择这个最高价值的物品呢?如果不选它,那必定是在它的截止日期可以售出更高价的物品,但是它已经是最高价的啦,所以一定要卖它。
      2. 有没有可能在之前卖它可以获利更大呢?如果可以,必然是有某个物品B本来不能卖,现在能卖了,可是A和B仍然在B的deadline前占了两个位置,完全可以在A的deadline卖出A
    2. 优先队列和sort基本无区别。
  • 并查集优化:

    1. 优化查找,取消 vispar[i] 代表 i 之前的最末空闲。
    2. 每卖出一个物品,如在第 i 天卖,则 par[i] 要改成 i - 1
    3. par[i] 如果是 0 ,说明这个物品没法卖。

代码:

  • 优先队列贪心:141ms 988kB
//141ms		988kB


#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>

using namespace std;

const int maxn = 10005;

int N;
int ans;
bool vis[maxn];
struct NODE{
	int p;
	int d;
	friend bool operator < (NODE a , NODE b)
	{
		if(a.p == b.p)
			return a.d < b.d;
		return a.p < b.p;
	}
	NODE(int _p,int _d) : p(_p) , d(_d) {} ;
};
priority_queue <NODE , vector<NODE> , less<NODE> > Q;
void INIT(){
	ans = 0;
	memset(vis , 0 , sizeof(vis));
	return ;
}

int main(){
	while(cin>>N){
		INIT();
		while(N--){
			int a,b;
			scanf("%d%d" , &a , &b);
			Q.push(NODE(a,b));
		}
		while(Q.size()){
			NODE cur = Q.top() ; Q.pop() ;
			int d = cur.d;
			while(d){
				if(!vis[d]){
					vis[d] = true;
					ans += cur.p ;
					break;
				}
				d--;
			}
		}
		cout<<ans<<endl;
	} 
	return 0;
}
  • sort贪心:141ms 820kB
//141ms		820kB


#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>

using namespace std;

const int maxn = 10005;

int N;
int ans;
bool vis[maxn];
struct NODE{
	int p;
	int d;
	friend bool operator < (NODE a , NODE b)
	{
		if(a.p == b.p)
			return a.d > b.d;
		return a.p > b.p;
	}
};
NODE node[maxn];

void INIT(){
	ans = 0;
	memset(vis , 0 , sizeof(vis));
	return ;
}

int main(){
	while(cin>>N){
		INIT();
		for(int i=0;i<N;i++){
			int a,b;
			scanf("%d%d" , &node[i].p , &node[i].d);
		}
		sort(node , node+N);
		for(int i=0;i<N;i++){
			int d = node[i].d ;
			while(d){
				if(!vis[d]){
					vis[d] = true;
					ans += node[i].p;
					break;
				}
				d--;
			}
		}
		cout<<ans<<endl;
	} 
	return 0;
}
  • 并查集优化:63ms 1020kB
//63ms		1020kB


#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>

using namespace std;

const int maxn = 10005;

int N;
int ans;
struct NODE{
	int p;
	int d;
	friend bool operator < (NODE a , NODE b)
	{
		if(a.p == b.p)
			return a.d < b.d ;
		return a.p < b.p ;
	}
	NODE(int p , int d) : p(p) , d(d) {} ;
};
priority_queue <NODE , vector<NODE> , less<NODE> > Q;
int par[maxn];

void INIT(){
	ans = 0;
	memset(par , -1, sizeof(par));
	return ;
}

int FIND(int i){
	return par[i] == -1 ? i : par[i] = FIND(par[i]);
}

int main(){
	while(cin>>N){
		INIT();
		int a, b;
		for(int i=1;i<=N;i++){
			scanf("%d%d" , &a , &b);
			Q.push(NODE(a,b));
		}
		while(Q.size()){
			NODE cur = Q.top() ; Q.pop() ;
			int d = cur.d;
			int pard = FIND(d);
			if(!pard)
				;
			else{
				par[pard] = pard - 1;
				ans += cur.p;
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}
import numpy as np import matplotlib.pyplot as plt # 随机生成超市和小区位置及需求 def generate_locations_and_demands(num_supermarkets, num_communities): supermarket_locations = np.random.rand(num_supermarkets, 2) * 100 # 随机生成超市位置 supermarket_demands = np.random.randint(10, 100, num_supermarkets) # 随机生成超市需求 community_locations = np.random.rand(num_communities, 2) * 100 # 随机生成小区位置 community_demands = np.random.randint(10, 100, num_communities) # 随机生成小区需求 return supermarket_locations, supermarket_demands, community_locations, community_demands # 极坐标转换分群 def polar_coordinate_clustering(locations): angles = np.arctan2(locations[:, 1], locations[:, 0]) sorted_indices = np.argsort(angles) return sorted_indices # 最近插入法规划路线 def nearest_insertion(locations): route = [0] unvisited = list(range(1, len(locations))) while unvisited: min_distance = float('inf') best_insertion = None best_node = None for node in unvisited: for i in range(len(route)): current_distance = np.linalg.norm(locations[route[i]] - locations[node]) if current_distance < min_distance: min_distance = current_distance best_insertion = i best_node = node route.insert(best_insertion + 1, best_node) unvisited.remove(best_node) return route # 可视化展示 def visualize_route(locations, route): plt.figure() plt.scatter(locations[:, 0], locations[:, 1], c='b') for i in range(len(route) - 1): start = locations[route[i]] end = locations[route[i + 1]] plt.plot([start[0], end[0]], [start[1], end[1]], 'r-') plt.plot([locations[route[-1]][0], locations[route[0]][0]], [locations[route[-1]][1], locations[route[0]][1]], 'r-') plt.show() # 主函数 def main(): num_supermarkets = 5 num_communities = 10 supermarket_locations, supermarket_demands, community_locations, community_demands = generate_locations_and_demands(num_supermarkets, num_communities) all_locations = np.vstack((supermarket_locations, community_locations)) all_demands = np.hstack((supermarket_demands, community_demands)) # 极坐标转换分群 sorted_indices = polar_coordinate_clustering(all_locations) sorted_locations = all_locations[sorted_indices] # 最近插入法规划路线 route = nearest_insertion(sorted_locations) # 可视化展示 visualize_route(sorted_locations, route) # 信息输出 print("路线规划:", route) print("需求信息:", all_demands) if __name__ == "__main__": main() 根据上述代码进行更改修正,代码所生成的图像用PyCharm能生成出来
最新发布
10-21
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值