Nothing for nothing ( 七 )

P1090 合并果子

链接:https://www.luogu.org/problemnew/show/P1090

题意:就是用最小的力气把所有的果子堆合并在一起,输出这个力气。

题解:看到题目很容易想到优先队列,按照从小到大的顺序,以此取出两个,再记录所用的力气,然后把合并之后的果子堆,再压入优先队列,按照上述方法接着操作。

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
priority_queue<int, vector<int>, greater<int> >q;//优先队列按照从小到大的顺序
int main(){
    int n, t, i;
    cin>>n;
    for(i = 0; i < n; i++){
        cin>>t;
        q.push(t);
    }
    long long sum = 0;
    while(!q.empty()){
        int a = q.top();
        q.pop();
        int b = q.top();
        q.pop();
        sum += a + b;//记录力气的花费
        if(!q.empty()){
           q.push(a+b);
        }
    }
    cout<<sum<<endl;

return 0;
}

 P1181 数列分段Section I

链接:https://www.luogu.org/problemnew/show/P1181

题意:本题就是一段长度为N的数组,按照几个数的和小于等于m,问最小可以分成几段

题解:遍历一遍,用k记录几个数的和,sum记录可以分的段数,如果k大于m那么k=此时的数,最后输出结果。

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
int main(){
    int n, m;
    cin>>n>>m;
    int i, t, sum = 0, k = 0;
    for(i = 0; i < n; i++){//遍历
        cin>>t;
        if(k + t <= m){//如果总数小于m
            k += t;
        }
        else {
            k = t;
            sum ++;
        }
    }
    cout<<sum+1<<endl;//最后一个没有记录所以需要+1;

return 0;
}

P1208 [USACO1.3]混合牛奶 Mixing Milk

题意:已知需要牛奶的吨数,求出购买牛奶的最小花费。

题解:就是把牛奶的价格排序,按照从小到打得顺序,遍历一遍,如果牛奶的吨数小于等于需求接着往下遍历,此外还需记录已经购买多少牛奶,还有花费的金额。直到牛奶的吨数大于需求的,用需要的牛奶吨数减去已经购买的,乘以此时的价格,然后加上之前的金额,这就是最小的花费。

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
struct milk{
       int kind, val;
}M[5005];
bool cmp(milk A, milk B){//按照从小到大的顺序
     return A.val < B.val;
}
int main(){
    int n, m, k = 0, i;
    cin>>n>>m;
    long long sum = 0;
    for(i = 0; i < m; i++){
        cin>>M[i].val>>M[i].kind;
    }
    sort(M, M + m,cmp);//排序
    for(i = 0; i < m; i++){
        if(k + M[i].kind <= n){//如果此时购买牛奶的数量小于需求量
            sum += M[i].kind*M[i].val;
            k += M[i].kind;
        }
        else{//此时牛奶的数量大于需求量
            sum += ((n - k) * M[i].val);
            break;//这个是非常的有必要,如果没有回接着遍历会是总金额偏大

        }
    }
    cout<<sum<<endl;
return 0;
}

P1223 排队接水

链接:https://www.luogu.org/problemnew/show/P1223

题意:就是一群人排队接水,问最平均等待时间,以及如何排序是使这个等待时间最小。

题解:只有接水时间最小的人在前面接水,所以把接水时间按照从小到大的顺序,接水是均等待时间最小,排在自己前面所有人接水时间之和就是此人等待时间,再把所有人等待时间加在一起除以总人数就是平均等待时间。

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
struct water{
       int order, time;//order记顺序,time记录接水的时间
}w[1005];
bool cmp(water A, water B){
     return A.time < B.time;
}
int main(){
    int n, i;
    cin>>n;
    for(i = 0; i < n; i++){
        cin>>w[i].time;
        w[i].order = i + 1;
    }
    sort(w, w + n, cmp);
    long long ans = 0, sum = w[i].time;
    for(i = 1; i < n; i++){
        sum += w[i-1].time;
        ans += sum;
    }
    for(i = 0; i < n; i++){
        cout<<w[i].order<<' ';
    }
    cout<<endl;
    double t = (ans*(1.0)) / n;
    printf("%.2lf\n", t);
return 0;
}

P1094 纪念品分组

链接:https://www.luogu.org/problemnew/show/P1094

题意:就是是两个人礼物价值之和小于n,最少有多少种划分

题解:把价值大于n/2的划分在一组,用数组a来记录,把价值小于n/2用数组b来记录,a按照从大到小的顺序,b按照从小到大的顺序,然后开始遍历,用i来记录a的位置,用j来记录b的位置,如果a[i]+b[j] <= n, 化分个数m++,直到i<a的长度&&j<b的长度,循环结束。最后m需要加上a中剩余的,加上b中剩余的除以2向上取整,这就是最终结果。

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
int a[30003], b[30003];
bool cmp(int a, int b){
     return a > b;
}
int main(){
    int n, m;
    cin>>n>>m;
    int i, j, t, cn = 0, cnt = 0;
    for(i = 0; i < m; i++){
        cin>>t;
        if(t > n/2)a[cn++] = t;
        else b[cnt++] = t;
    }
    sort(a,a + cn, cmp);
    sort(b, b + cnt);

    int ans = 0;
     i = 0, j = 0;
    while(i < cn && j < cnt){
        if(a[i] + b[j] <= n){
            ans++;
            i++;
            j++;
        }
        else {
            i++;
        }
    }
    int k = cnt - j;
    if(k % 2 == 0)k /= 2;
    else k = k / 2 + 1;
    ans += cn - j + k;
    cout<<ans<<endl;
return 0;
}

P1803 凌乱的yyy / 线段覆盖

链接:https://www.luogu.org/problemnew/show/P1803

题意:就是yyy打比赛,已知每场比赛的开始时间和结束时间,

题解:按照结束的时间按照从小到大的顺序,如果开始的此时开始的时间大于之前结束的时间比赛数量+1.

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
pair<int, int>p[1000005];
typedef pair<int, int>P;
int cmp(P a, P b){
     return a.second < b.second;
}
int main(){
    int n, i, ans = 0;
    cin>>n;
    for(i = 0; i < n; i++){
        cin>>p[i].first>>p[i].second;
    }
    sort(p, p + n, cmp);
    int t = p[0].second;
    for(i = 1; i < n; i++){
        if(p[i].first >= t){
            ans++;
            t = p[i].second;
        }
    }
    cout<<ans+1<<endl;//第一场比赛没有算进去,所以需要+1;

return 0;
}

P1031 均分纸牌

链接:https://www.luogu.org/problemnew/show/P1031

题意:就是进行最少的操作是所有人的纸牌数相等,两端的人只能向中间传送纸牌。

题解:求出平均值,然后所有的数据减去平均值,然后遍历一遍,按照从左向右的顺序。

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
int a[10005];
int main(){
    int n, i, cn = 0, ave = 0;
    cin>>n;
    for(i = 0; i < n; i++){
        cin>>a[i];
        ave += a[i];
    }
    ave /= n;
    for(i = 0; i < n; i++)a[i] -= ave;
    for(i = 0; i < n; i++){
        if(a[i] == 0)continue;
        a[i+1] += a[i];
        cn++;

    }
    cout<<cn<<endl;

return 0;
}

猜你喜欢

转载自blog.csdn.net/REfusing/article/details/81408299