7/31 CSU-ACM2018暑期训练7-贪心

比赛链接
A-CSU - 1588
现在有n堆果子,第i堆有ai个果子。现在要把这些果子合并成一堆,每次合并的代价是两堆果子的总果子数。求合并所有果子的最小代价。

Input
第一行包含一个整数T(T<=50),表示数据组数。
每组数据第一行包含一个整数n(2<=n<=1000),表示果子的堆数。
第二行包含n个正整数ai(ai<=100),表示每堆果子的果子数。

Output
每组数据仅一行,表示最小合并代价。

Sample Input
2
4
1 2 3 4
5
3 5 2 1 4
Sample Output
19
33
【分析】:使用优先队列,注意cmp是小的优先,所以是priority_queue<int,vector ,greater >q
1.把果子都push进q内;
2.当q的size大于1,不断取最小的两个top相加,如何取呢?当取完一个top就pop掉,那么剩下的那个顶替为最小,合并就是把这两个之和push进q,然后记录a+b权值的和

#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <typeinfo>
#include <fstream>
#include <map>
#include <stack>
typedef long long ll;
using namespace std;
#define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
#define test freopen("test.txt","r",stdin)
#define maxn 1000005
#define mod 10007
#define eps 1e-5
const int inf=0x3f3f3f3f;
const ll infll = 0x3f3f3f3f3f3f3f3fLL;
int n,x;
int t,sum[maxn];
int ans,a,b;
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        priority_queue<int,vector<int>,greater<int> > q;
        while(!q.empty()) q.pop();
        ans=0;
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%d",&x);
            q.push(x);
        }
        while(q.size()!=1)
        {
            a=q.top();
            q.pop();
            b=q.top();
            q.pop();
            q.push(a+b);
            ans+=a+b;
        }
        cout<<ans<<endl;
    }
}

B-HDU - 1789

【题意】:给出n个作业的截止日期,和n个作业不交所扣掉的分数,要求输出扣除分数做少的方案。
【分析】:已知扣分和截止日期,要求扣分最少。那么我按扣分由大到小排序,分数相同则截止日期由短到长排序。
为什么呢?因为我们最终目的是扣分最少,那么扣分权重大的自然要尽快完成,以免超过dd(deadline)而扣很大,扣分分数相同的话dd由短到长排序,自然是为了将马上就要交的作业先完成。总而言之,就是要优先考虑:扣分多、急着交的作业。
贪心策略是:
1.扣除分数大的先做
2.扣除分数相同,时间先截止的先做
3.做一件事的时候,从截止时间从后往前开始向第一天遍历,如果当天没有被作业占据则标记为占据。做这件事的日期越大越靠后越好。为什么呢?因为留给dd短的时间的余地就多些。
4.如果不能满足3的条件,则为不能完成

7
1 4 6 4 2 4 3
3 2 1 7 6 5 4
------------------
After Sort:
4 7
2 6
4 5
3 4
1 3
4 2
6 1
-------------------
j = 4
j = 2
j = 3
j = 1
j = 0
day = 1 score = 3
j = 0
day = 4 score = 2
j = 6
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <typeinfo>
#include <fstream>
#include <map>
#include <stack>
typedef long long ll;
using namespace std;
#define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
#define test freopen("test.txt","r",stdin)
#define maxn 1000005
#define mod 10007
#define eps 1e-5
const int inf=0x3f3f3f3f;
const ll infll = 0x3f3f3f3f3f3f3f3fLL;
int n,x,t,sum,j,d;
int vis[maxn];
struct node
{
    int day;
    int score;
}a[maxn];
bool cmp(node a,node b)
{
    return a.score>b.score;
    return a.day<b.day;
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        memset(vis,0,sizeof(vis));
        scanf("%d",&n);
        for(int i=0;i<n;i++)
            scanf("%d",&a[i].day);
        for(int i=0;i<n;i++)
            scanf("%d",&a[i].score);
        sort(a,a+n,cmp);
        sum=0;
        for(int i=0;i<n;i++)
        {
            d=a[i].day;
            for(j=d;j>0;j--)
            {
                if(!vis[j])
                {
                    vis[j]=1;
                    break;
                }
            }
            if(!j) sum+=a[i].score;
        }
        printf("%d\n",sum);
    }
}

猜你喜欢

转载自www.cnblogs.com/Roni-i/p/9399583.html