贪心1合集
青藤oj #10021. 均分纸牌
题目描述
有 N 堆纸牌,编号分别为 1,2,…, N。每堆上有若干张,但纸牌总数必为 N 的倍数。可以在任一堆上取若于张纸牌,然后移动。
移牌规则为:在编号为 1 堆上取的纸牌,只能移到编号为 2 的堆上;在编号为 N 的堆上取的纸牌,只能移到编号为 N-1 的堆上;其他堆上取的纸
牌,可以移到相邻左边或右边的堆上。
现在要求找出一种移动方法,用最少的移动次数使每堆上纸牌数都一样多。
例如 N=4,4 堆纸牌数分别为:① 9 ② 8 ③ 17 ④ 6 移动3次可达到目的: 从 ③ 取 4 张牌放到 ④ (9 8 13 10) -> 从 ③ 取 3
张牌放到 ②(9 11 10 10)-> 从 ② 取 1 张牌放到①(10 10 10 10)。
输入格式
N(N 堆纸牌,1 <= N <= 100)
A1 A2 … An (N 堆纸牌,每堆纸牌初始数,l<= Ai <=10000)
输出格式
所有堆均达到相等时的最少移动次数。
思路
设a[i]为第I堆纸牌的张数(0<=I<=n),v为均分后每堆纸牌的张数,s为最小移动次数。
我们用贪心算法,按照从左到右的顺序移动纸牌。如第I堆的纸牌数不等于平均值,则s加1,分两种情况移动:
1.若a[i]>v,则将a[i]-v张从第I堆移动到第I+1堆;
2.若a[i]<v,则将v-a[i]张从第I+1堆移动到第I堆。
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
int c[500];
int n, sum = 0;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> c[i];
sum += c[i];
}
int avg = sum / n;
int count = 0;
for (int i = 0; i < n; i++) {
if (c[i] != avg) {
c[i + 1] += c[i] - avg;
count++;
}
}
cout << count << endl;
}
青藤oj #10045. 零件分组
题目描述
某工厂生产一批棍状零件,每个零件都有一定的长度 Li和重量Wi 。现在为了加工需要,要将它们分成若干组,使每一组的零件都能排成一个长度和重量都不下降(若 i<j,则Li<=Lj ,Wi<=Wj )的序列。请问至少要分成几组?
输入格式
第一行为一个整数N(N<=1000) ,表示零件的个数。第二行有N 对正整数,每对正整数表示这些零件的长度和重量,长度和重量均不超过 。
输出格式
仅一行,即最少分成的组数。
思路
dp[i]=max(dp[j]+1,dp[i])
代码
#include<bits/stdc++.h>
using namespace std;
struct str
{
int l,r;
}a[11000];
int n;
int dp[11000]={0},ans;
bool cmp(str x,str y)
{
if(x.l==y.l) return x.r<y.r;
return x.l<y.l;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i].l>>a[i].r;
}
sort(a+1,a+1+n,cmp);
for(int i=2;i<=n;i++)
{
for(int j=1;j<i;j++)
{
if(a[j].r>a[i].r)
{
dp[i]=max(dp[j]+1,dp[i]);
}
}
ans=max(dp[i],ans);
}
cout<<ans+1;
}
青藤oj #10040. 纪念品组合
题目描述
元旦快到了,校学生会让乐乐负责新年晚会的纪念品发放工作。为使得参加晚会的同学所获得的纪念品价值相对均衡,他要把购来的纪念品根据价格进行分组,但每组最多只能包括两件纪念品,并且每组纪念品的价格之和不能超过一个给定的整数。为了保证在尽量短的时间内发完所有纪念品,乐乐希望分组的数目最少。你的任务是写一个程序,找出所有分组方案中分组数最少的一种,输出最少的分组数目。
输入格式
输入文件包含n+2 行: 第 1 行包括一个整数w ,为每组纪念品价格之和的上限。 第 2 行为一个整数n ,表示购来的纪念品的总件数。 第 3~ n +2 行每行包含一个正整数 p i (5 <= p i <= w ),表示所对应纪念品的价格。
输出格式
输出文件仅一行,包含一个整数,即最少的分组数目。
思路
贪心,没啥好说的。。。
代码
#include<bits/stdc++.h>
using namespace std;
bool cmp(int a, int b)
{
return a < b;
}
int main()
{
int limit, num, s = 0;
cin >> limit >> num;
vector<int> money;
int temp;
for (int i = 0; i < num; i++)
{
cin >> temp;
money.push_back(temp);
}
sort(money.begin(), money.end(), cmp);
for (int i = 0; i < num; i++)
{
for (int j = num - 1; j >= i, money[i] != 0; j--)
{
if (j == i)
{
s++;
break;
}
if (money[j] != 0 && money[i] != 0 && money[i] + money[j] <= limit)
{
s++;
money[j] = 0;
break;
}
}
}
cout << s;
return 0;
}
青藤oj #10036. 排队接水
题目描述
有n个人在一个水龙头前排队接水,假如每个人接水的时间为Ti,请编程找出这n个人排队的一种顺序, 使得n个人的平均等待时间最小。 n<=1000,等待的时间小于等于1000
输入格式
输入文件共两行,第一行为n;第二行分别表示第 1 个人到第n个人每人的接水时间T1,T2,…,Tn,每 个数据之间有 1 个空格。
输出格式
输出有一行,最少平均排列方案下的平均等待时间(输出结果精确到小数点后两位)。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n;
int main()
{
scanf("%d",&n);
ll sum=0;
int *a=new int[n+1];
for(int i=0;i<n;i++)
{
scanf("%I64d",&a[i]);
}
sort(a,a+n);
for(int i=0;i<n;i++)
{
sum+=a[i]*(n-i);
}
printf("%.2lf\n",(1.0*sum/n));
}
青藤oj #10081. 活动选择
题目描述
学校在最近几天有n个活动,这些活动都需要使用学校的大礼堂,在同一时间,礼堂只能被一个活动使用。由于有些活动时间上有冲突,学校办公室人员只好让一些活动放弃使用礼堂而使用其他教室。
现在给出n个活动使用礼堂的起始时间bi和结束时间ei(bi < ei<=32767),请你帮助办公室人员安排一些活动来使用礼堂,要求安排的活动尽量多。
输入格式
第一行一个整数n(n<=1000); 接下来的n行,每行两个整数,第一个bi,第二个是ei(bi < ei<=32767)
输出格式
输出最多能安排的活动个数
代码
#include<bits/stdc++.h>
using namespace std;
int beginn[1001],endd[1001];
int n,sum=0;
void qsort(int,int);
void slove();
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&beginn[i],&endd[i]);
}
qsort(1,n);
slove();
return 0;
}
void qsort(int x,int y)
{
int l=x,r=y,m=endd[(x+y)/2];
while(l<=r)
{
while(endd[l]<m)l++;
while(endd[r]>m)r--;
if(l<=r)
{
int m=endd[l];endd[l]=endd[r];endd[r]=m;
int n=beginn[l];beginn[l]=beginn[r];beginn[r]=n;
l++;r--;
}
}
if(l<y)qsort(l,y);
if(r>x)qsort(x,r);
}
void slove()
{
int lastt=-1;
for(int i=1;i<=n;i++)
{
if(beginn[i]>=lastt)
{
sum++;
lastt=endd[i];
}
}
printf("%d",sum);
}
青藤oj #10082. 整数区间
题目描述
给n个区间,形式为[a, b],a和b均为整数,且a < b。求一个最小的整数点的集合,使得每个区间至少 1 个元素属于这个集合。求这个集合的元素个数。
输入格式
第1行:1个整数n(1 <= n <= 10000)接下来n行,每行2个整数,表示区间的左右端点a, b(0 <=a < b <= 10000)
输出格式
第1行:1个整数,表示集合的元素的个数
代码
#include<bits/stdc++.h>
using namespace std;
struct range
{
int from,to;
}a[10000];
bool cmp(range x,range y)
{
return x.to<y.to;
}
int main()
{
int n,i,sum=0;
cin>>n;
for(i=0;i<n;i++)
cin>>a[i].from>>a[i].to;
sort(a,a+n,cmp);
int x;
for(i=0,x=-1;i<n;i++)
{
if(x>=a[i].from) continue;
x=a[i].to;
sum++;
}
cout<<sum;
return 0;
}