POJ2376贪心Cleaning Shifts、CodeForces 334A Candy Bags

本文探讨了两个使用贪心策略解决的计算机科学问题。第一个是关于分配奶牛工作班次的问题,通过排序并按开始时间选择最大范围的班次来达到最少的奶牛数量。第二个问题是糖果包分配,通过分析每行糖果数的差异,揭示了如何通过交换一半的包裹使每个朋友得到相同糖果的策略。这两个问题展示了贪心算法在组合优化中的应用。
摘要由CSDN通过智能技术生成

目录

 

POJ2376贪心Cleaning Shifts

题目大意

贪心:

代码:

CodeForces 334A Candy Bags

题意:

代码:


POJ2376贪心Cleaning Shifts

题目大意

给定cows的工作shift,尽可能少的cows使得每一个shift都有cows工作。如果无法完成则为-1.

贪心:

按开始sort。对于一个选定的区间,枚举所有左端点在这区间的,选择最大的(因为这样可以尽可能延申,比起较小的有利而无害)。时间复杂度O(n).

注意!!:离散连续性!,every shift,每一个点。也就是start<=end+1即可。

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cstdlib>
#include<map>
#include<cmath>
#include<vector>
#include<cstdio>

using namespace std;
typedef long long ll;
const int maxn = 25500;
typedef struct{
	int l;
	int r;
}cows_work;
cows_work  cows[maxn];
int n,t;
bool cmp(cows_work a,cows_work b){ 
	return a.l < b.l;
}
void check(){
	bool flag = false;
	int ans = 0;
	int rec = 0,rec_maxs = 0;
	/*
	随时双for,但是只是O(n),因为内层for循环次数加到了外层循环中。
	也就是比如内层循环2次,外层也相当于循环两次,i对应已经加上了。 
	*/
	for(int i = 0;i < n;i++){
		if(rec >= t){
			flag = true;
			break;
		}
		rec_maxs = 0;//可以伸展的最远地方以及idx为对应下标 
		int j;
		for(j = i;j < n;j++){
			//!!! 离散连续!!!! 
			if(cows[j].l > rec+1)	break;//控制只能寻找左端点在目前已拼接之前的 
			if(rec_maxs < cows[j].r)
				rec_maxs = cows[j].r;
		}
		//j为第一个不满足的或者等于n 
		if(rec_maxs == 0)	break;//意味着没有可以拼接的了 
		ans++;
		rec = rec_maxs;//记录下已经拼接的 
		i = j-1;//i为这次讨论的最后一个   自加后就是需要下一轮讨论的 
	}
	if(rec >= t)	flag = true;
	if(flag)	cout<<ans<<endl;
	else cout<<"-1"<<endl;
}
int main(){
	cin.tie(0);cout.tie(0);
	cin>>n>>t;
	for(int i = 0;i < n;i++)	cin>>cows[i].l>>cows[i].r;
	sort(cows,cows+n,cmp);
	check();
	return 0;
}

CodeForces 334A Candy Bags

题意:

1-n^n中背包,每一个bag里面有对应的糖果1-n^n。如果分给n个friends,每人n个包裹,并且对应candy都一样。

思路:

1            2               3     …….            N

N+1        n+2            n+3   …….            2n

……..

n^n-n+1    n^n-n+2     n^n-n+3  ……..               n^n

发现 对应列元素第一行最后一行相差n(n-1)(相邻两行相差n,相邻n-1行)。第一行与最后一行相差为[n*(n-1)]*n(每一列相差n(n-1))。如果调换x对的话相差[n*(n-1)]*n-n*(n-1)*x*2。当x=n/2时(even number的用处),相差为0,也就是调换一半。对应第二行倒数第二行以此类推。

       n*[n(n-m)]-n*(n-m)*x*2 = 0  m=n/2;(m为第m行,1<=m<=n/2)

或者这样想,最小的几个+最大的几个就行,这几个共n个,所以最大的n/2+最小的n/2即可。

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cstdlib>
#include<map>
#include<cmath>
#include<vector>
#include<cstdio>

using namespace std;
typedef long long ll;
const int maxn = 1e6+50;

int main(){
	cin.tie(0);cout.tie(0);
	int n;
	cin >> n;
	int cnt = 0;
	int sum = 0;
	for(int l = 1,r = n*n;l <= r;l++,r--){
		cnt+=2;
		cout << l << " " << r;
		if(cnt == n){
			cnt = 0;
			cout << endl;
		}
		else cout<<' ';
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值