codeforce447 D SGU 548 贪心+优先队列

codeforce447 D - DZY Loves Modification 
题意:
有一个n*m的矩阵,每次可以选择一行或者一列,可以得到这行或这列的所有元素sum的积分,
然后使这一列/行的每一个元素都减少p,接着再选择一行或一列,共操作k次,n,m<=1000,k<=1000000
求最多能得到多少积分

思路:
每次选择sum最大的行或者列,但是时间复杂度太大,过不去~
若选择一行,则每个列的sum一定减少p,同理;
若选择的行数和列数确定下来了,选择i行,k-i列,那么行和列之间谁选选择就没有影响;
因为在选择行的时候,每一列都的sum都减少p,每一列的相对大小没有变化,前k-i大的列还是那几列,同列。
所以可以用优先队列O(n)预处理出row_sum[i]和col_sum[k-i]的值。选i行则消耗了每列的i*p的大小,共k-i列,故共消耗了i*(k-i)*p,答案为
max( row_sum[i], col_sum[k-i])- i*(k-i)*p

注意:!!!!!WA了很久T.T,因为i*(k-i)*p会超过int范围!!!

 1 /*===============================================================
 2 *   Copyright (C) 2014 All rights reserved.
 3 *
 4 *   File Name: codeforces447_D_greedy.cpp
 5 *   Author:sunshine
 6 *   Created Time: 2014年07月23日
 7 *
 8 ================================================================*/
 9 #include <map>
10 #include <queue>
11 #include <stack>
12 #include <math.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <iostream>
16 #include <algorithm>
17
18 using namespace std;
19
20 int arr[1001][1001];
21 long long row_sum[1000001];
22 long long col_sum[1000001];
23
24 int main(){
25     int n,m,k,p;
26     cin >> n >> m >> k >> p;
27
28     priority_queue<int>row,col;
29
30     for(int i = 0;i < n;i ++){
31         long long tmp =  0;
32         for(int j = 0;j < m;j ++){
33             cin >> arr[i][j];
34             tmp += arr[i][j];
35         }
36         row.push(tmp);
37     }
38
39     for(int j = 0;j < m;j ++){
40         long long tmp = 0;
41         for(int i = 0;i < n;i ++){
42             tmp += arr[i][j];
43         }
44         col.push(tmp);
45     }
46
47     row_sum[0] = 0;
48     for(int i = 1;i <= k;i ++){
49         row_sum[i] = row_sum[i - 1] + row.top();
50         row.push(row.top() - m * p);
51         row.pop();
52     }
53
54     col_sum[0] = 0;
55     for(int i = 1;i <= k;i ++){
56         col_sum[i] = col_sum[i-1] + col.top();
57         col.push(col.top() - n * p);
58         col.pop();
59     }
60
61     long long res = row_sum[0] + col_sum[k];
62     for(int i = 1;i <= k;i ++){
63         res = max(res, row_sum[i] + col_sum[k - i] - (long long)i * (k - i) * p);
64     }
65     cout << res << endl;
66     return 0;
67 }

SGU 548 Dragons and Princesses
题意:
唐僧从起点1出发,依次从1到2到3……到n,第n位一定是一位公主,在2~n-1中可能是公主,也可能是龙,
d表示龙,p表示公主,每只龙有di个金币,每位公主有pi的美丽值,杀死一只龙就可以得到相应的财富值。
唐僧喜欢位置为n的那位公主,所以要和位置为n的公主结婚,所以他不能被其他公主喜欢上,必须被最后一个公主喜欢。
他被公主喜欢上的条件是:在遇到位置为i的公主是,如果pi小于等于唐僧杀死的龙的数量,那么公主
就认为唐僧很V5,会喜欢上唐僧,问题,唐僧成功和位置为n的公主结婚的情况下,最多能得到多少金币。
如果不能结婚,输出-1。

思路:
利用优先队列遇到龙就吃掉,遇到公主,发现吃多了,就把多余的小的都吐出来,当然遇到最后一个公主的时候不需要吐出来。

 1 #include <stdio.h>
 2 #include <iostream>
 3 #include <queue>
 4 #include <algorithm>
 5
 6 using namespace std;
 7
 8 struct node{
 9     int key;
10     int id;
11     friend bool operator < (node a,node b){
12         return a.key > b.key;
13     }
14 }dro;
15
16 int arr[200005];
17
18 int main(){
19     int n;
20     char ch[10];
21     int key;
22     int base;
23     while(scanf("%d", &n) != EOF){
24
25         priority_queue<node>que;
26
27         for(int i = 0;i < n - 1;i ++){
28             scanf("%s %d", ch, &key);
29
30             if(ch[0] == ‘d‘){
31                 dro.key = key;
32                 dro.id = i + 2;
33                 que.push(dro);
34             }
35             if(ch[0] == ‘p‘){
36                 if(i != n - 2){
37                     while(que.size() >= key){
38                         que.pop();
39                     }
40                 }else{
41                     base = key;
42                 }
43             }
44         }
45
46
47         if(que.size() < base){
48             puts("-1");
49         }else{
50             int res = 0;
51             int top = 0;
52             while(que.size()){
53                 dro = que.top();
54                 que.pop();
55             //    printf("key:%d id:%d\n",dro.key,dro.id);
56                 res += dro.key;
57                 arr[top++] = dro.id;
58             }
59
60             sort(arr,arr + top);
61
62             printf("%d\n%d\n",res,top);
63
64             for(int i = 0;i < top - 1;i ++){
65                 printf("%d ",arr[i]);
66             }
67             printf("%d\n",arr[top - 1]);
68         }
69     }
70     return 0;
71 }

codeforce447 D SGU 548 贪心+优先队列

时间: 2024-11-29 06:21:07

codeforce447 D SGU 548 贪心+优先队列的相关文章

poj3190Stall Reservations(贪心+优先队列)

题目链接: 啊哈哈,点我点我 思路: 首先根据挤奶时间的先后顺序排序...然后将第一头牛加入优先队列..然后就是加入优先队列的牛应该根据越早结束挤奶那么优先级更高,如果时间结束点相等,那么开始时间早的优先级高... 然后从前向后枚举.如果碰到有牛的挤奶时间的开始值大于优先队列的首部的结束值,那么说明这两头牛可以一起公用一个挤奶房..然后从优先队列中删除这头牛..那么这个问题就得到解决了... 题目: Language: Default Stall Reservations Time Limit:

poj 2431 Expedition (贪心+优先队列)

Expedition Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6890   Accepted: 2065 Description A group of cows grabbed a truck and ventured on an expedition deep into the jungle. Being rather poor drivers, the cows unfortunately managed to

BZOJ 2151 种树 贪心+优先队列+HASH

题意:链接 方法:贪心+优先队列 解析: 首先裸上贪最大的肯定不对. DP可行么?可行,两个数组一个记录选一个记录不选好像差不多n^2? 不过还是想想贪心. 贪最大的为什么不对? 因为有可能它旁边的两个加起来比它更优越? 所以能否找到一点关系呢? 既然话都说到这了,两个加起来可能更优越. 所以我们在选了最大的之后是否应该回推一个值呢?代表选旁边俩. 我们发现选旁边俩是两个单位,选一个是一个单位,如果我们推回去某个值后这个值相当于对应删去一个单位选两个单位,即增加一个单位,这显然不会影响最终我们选

POJ1456Supermarket(贪心+优先队列)

Supermarket Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9103   Accepted: 3891 Description A supermarket has a set Prod of products on sale. It earns a profit px for each product x∈Prod sold by a deadline dx that is measured as an int

[POJ1456]Supermarket(贪心 + 优先队列 || 并查集)

传送门 1.贪心 + 优先队列 按照时间排序从前往后 很简单不多说 ——代码 1 #include <queue> 2 #include <cstdio> 3 #include <iostream> 4 #include <algorithm> 5 #define N 10001 6 7 int n, t, ans; 8 std::priority_queue <int, std::vector <int>, std::greater &l

POJ 3190 Stall Reservations(贪心+优先队列优化)

Description Oh those picky N (1 <= N <= 50,000) cows! They are so picky that each one will only be milked over some precise time interval A..B (1 <= A <= B <= 1,000,000), which includes both times A and B. Obviously, FJ must create a reserv

hihoCoder 1309:任务分配 贪心 优先队列

#1309 : 任务分配 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定 N 项任务的起至时间( S1, E1 ), ( S2, E2 ), ..., ( SN, EN ), 计算最少需要多少台机器才能按时完成所有任务. 同一时间一台机器上最多进行一项任务,并且一项任务必须从头到尾保持在一台机器上进行.任务切换不需要时间. 输入 第一行一个整数 N,(1 ≤ N ≤ 100000),表示任务的数目. 以下 N 行每行两个整数 Si, Ei,(0 ≤ Si < 

Codeforces Round #FF/#255 D DZY Loves Modification --贪心+优先队列

题意:给你一个矩阵,每次选某一行或者某一列,得到的价值为那一行或列的和,然后该行每个元素减去p.问连续取k次能得到的最大总价值为多少. 解法: 如果p=0,即永远不减数,那么最优肯定是取每行或每列那个最大的取k次,所以最优解由此推出. 如果不管p,先拿,最后再减去那些行列交叉点,因为每个点的值只能取一次,而交叉点的值被加了两次,所以要减掉1次,如果取行A次,取列B次,那么最后答案为: res = dp1[A] + dp2[B] - B*(k-A)*p,可以细细体会一下后面那部分. 其中: dp1

POJ 1862 Stripies 贪心+优先队列

http://poj.org/problem?id=1862 题目大意: 有一种生物能两两合并,合并之前的重量分别为m1和m2,合并之后变为2*sqrt(m1*m2),现在给定n个这样的生物,求合并成一个的最小重量 思路: m1+m2 >=  2*sqrt(m1*m2) 所以每次取大的去合并,能变小. 直接优先队列就可以啦. #include<cstdio> #include<cmath> #include<queue> using namespace std;