导航
页内跳转 | 打开题目链接 |
---|---|
A | POJ_3617 |
B | POJ_3069 |
C | POJ_3253 |
D | POJ_2376 |
E | POJ_1328 |
F | POJ_3190 |
G | POJ_2393 |
H | POJ_1017 |
I | POJ_3040 |
J | POJ_1862 |
K | POJ_3262 |
A_Best Cow Line 回到顶部
题目大意:给个长度为n的字符串,构造一个字典序最小的字符串。构造时执行n次下述任意一种操作
1)从原字符串头部删除一个字符,加入构造字符串尾部
2)从原字符串尾部删除一个字符,加入构造字符串尾部
贪心策略:不断取S的开头和末尾中较小的字符放到T的末尾,如若相等,则比较下一对字符。
#include <iostream>
using namespace std;
//输入
int n;
char a[2005];
int main()
{
while(cin >> n) {
for(int i = 0; i < n; i++) {
cin >> a[i];
}
string res = ""; //保存答案
int l = 0, r = n-1; //l, r分别表示剩余字符串在原字符串a的起始与结束位置
while(l <= r) {
bool sign = false; //标记,true表示左边字符小于右边字符,否则为假
for(int i = 0; i +l <= r; i++) {
if(a[i+l] < a[r-i]) {
sign = true;
break;
}else if(a[l+i] > a[r-i]){
break;
}
//如果左右相等,则比较下一对
}
if(sign) { //左边字符小于右边字符
res += a[l++]; //++自增运算符,l++表示先运算,后l+1
}else {
res += a[r--];
}
}
//每80个字符,换一次行
for(int i = 0; i < n; i++) {
if(i % 80 == 0 && i) {
cout << endl;
}
cout << res[i];
}
}
return 0;
}
B_Saruman’s Army 回到顶部
题目大意:有N头牛每分钟吃d[i]朵花,农夫把每头牛送回牛舍需要花费2*t[i]时间(来回),求送完所有牛后,最少吃了多少花朵
贪心策略:不难想到每次运的牛为破坏的花朵最多的牛,即按照单位时间吃花量排序。
#include <iostream>
#include <algorithm>
using namespace std;
//输入
int N;
typedef struct {
int t, d;
}Data;
Data d[100005];
bool cmp(Data d1, Data d2) {
//按照运送时间内吃的花朵数量从大到小排序
/*
d1:2*d1.t*d2.d 先运送d1
d2:2*d2.t*d1.d 先运送d2
return 2 * d1.t * d2.d < 2* d2.t * d1.d
*/
return d1.t / (1.0 * d1.d) < d2.t / (1.0 * d2.d);
}
int main() {
while(cin >> N) {
for(int i = 0; i < N; i++) {
cin >> d[i].t >> d[i].d;
}
sort(d, d+N, cmp);
long long res = 0L; //保存答案
int time = 0; //保存当前运送牛已花费时间
for(int i = 0; i < N; i++) { //先运送吃花朵多的牛
res += 1L * time * d[i].d;
time += 2 * d[i].t;
}
cout << res << endl;
}
return 0;
}
C_Fence Repair 回到顶部
题目大意:给一根木板,将它锯为n块要求长度的木板,每次锯木板花费代价为模板长度,求花费代价最小值。
可将锯木板看做合并木板,便于理解
贪心策略:每次找寻长度最短与次短木板进行合并。
#include <iostream>
#include <queue>
using namespace std;
//输入
int N;
int l;
int main()
{
while(cin >> N) {
priority_queue<int, vector<int>, greater<int> > que; //优先队列(小根堆),队首元素为最小元素
for(int i = 0; i < N; i++) {
cin >> l;
que.push(l);
}
long long res = 0L; //保存答案,答案超过int类型表示范围
while(que.size() > 1) { //保证最少有两块木板可以合并,为1时表示已合并为1块木板
//找寻最短与次短长度木板
int t1 = que.top();
que.pop();
int t2 = que.top();
que.pop();
//答案加上此次花费代价
res += (long long)t1 + t2;
//合并后的木板加入待合并木板堆
que.push(t1+t2);
}
cout << res << endl;
}
return 0;
}
D_Cleaning Shifts 回到顶部
题目大意:给定N头牛和T个时间点,每头牛工作一段时间,求至少需要多少头牛课覆盖所有工作时间点(1~T)
贪心策略:每次从可选择牛中选择结束时间最迟的牛,注意题目不确保一定能完成覆盖所有工作时间
#include <iostream>
#include <algorithm>
using namespace std;
//输入
int N, T;
typedef struct {
int start, end;
}Data;
Data d[25005];
bool cmp(Data d1, Data d2) {
//自定义排序,按照开始时间从小到大排序,如果开始时间相同,按照结束时间从大到小排序
if(d1.start == d2.start) {
return d1.end > d2.end;
}
return d1.start < d2.start;
}
int main()
{
while(cin >> N >> T) {
for(int i = 0; i < N; i++) {
cin >> d[i].start >> d[i].end;
}
sort(d, d+N, cmp);
int res = 0; //保存答案
int r = 0; //当前选择的牛中工作结束时间最迟时间
for(int i = 0; i < N; ) {
int temp = r; //保存当前可工作牛的结束最迟时间
while(d[i].start <= (r+1) && i < N) {//确保下一头牛的工作开始时间在当前工作牛的结束时间之前
temp = max(temp, d[i].end); //找寻结束最迟时间
i++;
}
if(temp <= r) { //没有找到一头牛可以完成接下来的时间段的工作
break;
}else { //已找到,更新最迟时间并让答案加1
r = temp;
res++;
}
}
if(r < T) { //未完成所有工作
cout << -1 << endl;
}else {
cout << res << endl;
}
}
return 0;
}
E_Radar Installation 回到顶部
题目大意:地图上有n个在x轴上方的岛, 有一种半径为R的雷达,问在x轴上至少安装多少雷达可使所有岛屿均可被扫描
贪心策略:找寻每个岛屿可安装雷达区间,对区间按照结束点从小到大排序,然后开始遍历建立雷达。
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int INF = 0x3f3f3f3f;
//输入
int n, r;
int x, y;
typedef struct {
double start, end; //覆盖当前岛屿的雷达起止坐标
}Data;
Data d[1005];
bool cmp(Data d1, Data d2) {
//自定义排序,按照时间从小到大排序
if(d1.end == d2.end){
return d1.start < d2.start;
}
return d1.end < d2.end;
}
int main() {
int ans = 1;
while(cin >> n >> r) {
if(n == 0 && r == 0) {
break;
}
bool sign = true; //标记,如果为false则表示有岛屿雷达不可能覆盖到
for(int i = 0; i < n; i++) {
cin >> x >> y;
if(y > r) { //雷达不可能覆盖该岛屿
sign = false;
}else {
//求该岛屿起止坐标(雷达都在海岸线上(即x轴上),所以只需横坐标)
d[i].start = (double)x - sqrt((double)(r * r - y * y));
d[i].end = (double)x + sqrt((double)(r * r - y * y));
}
}
cout << "Case " << ans++ << ": ";
if(!sign) { //无解决方案
cout << -1 << endl;
continue;
}
sort(d, d+n, cmp);
int res = 0; //保存答案
double right = -1.0 * INF; //当前雷达覆盖最右位置
for(int i = 0; i < n; i++) {
if(d[i].start > right) { //需要添加新的雷达覆盖该岛屿
res++;
right = d[i].end; //更新雷达覆盖位置
}
}
cout << res << endl;
}
return 0;
}
F_Stall Reservations 回到顶部
题目大意:有N头奶牛需要挤奶,每头奶牛在挤奶时间段中独占一个栅栏位,问最少需要多少栅栏位供所有奶牛挤奶。输出栅栏个数且输出每头奶牛用的栅栏位编号,编号从1开始。
贪心策略:按开始时间顺序遍历所有奶牛并放入栅栏内, 维护栅栏队列,即每次判断是否有奶牛结束挤奶工作让出栅栏位,如果有则可不用申请栅栏,换头奶牛完成任务,否则再申请一个栅栏用于当前奶牛工作。
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
//输入
int N;
typedef struct Data {
int start, end; //起止时间
int id; //牛的编号
friend bool operator < (Data d1, Data d2) {
//重载'<'运算符,使得优先队列队首为已经挤奶的奶牛中结束时间最早的奶牛
if(d1.end == d2.end) {
return d1.start > d2.start;
}
return d1.end > d2.end;
}
}Data;
Data d[50005];
int res[50005]; //保存答案
bool cmp(Data d1, Data d2) {
//自定义排序方式,使得按照开始时间从小到大排序
if(d1.start == d2.start) {
return d1.end < d2.end;
}
return d1.start < d2.start;
}
int main() {
while(cin >> N) {
for(int i = 0; i < N; i++) {
cin >> d[i].start >> d[i].end;
d[i].id = i;
}
sort(d, d+N, cmp);
priority_queue<Data> que; //维护栅栏中正在挤奶的牛
que.push(d[0]); //压入第一头
int ans = 1; //当前栅栏数
res[d[0].id] = ans;
for(int i = 1; i < N; i++) {
Data temp = que.top();
if(temp.end < d[i].start) { //已有奶牛挤奶结束,当前奶牛可放入该栅栏中
que.pop(); //挤奶结束奶牛退出栅栏
res[d[i].id] = res[temp.id]; //和推出的奶牛在同一编号栅栏中
} else { //当前最早结束挤奶的奶牛还没有结束,即所有奶牛都没有结束挤奶,需要添加栅栏位
ans++;
res[d[i].id] = ans;
}
que.push(d[i]); //压入当前奶牛
}
cout << ans << endl;
for(int i = 0; i < N; i++) {
cout << res[i] << endl;
}
}
return 0;
}
G_Yogurt factory 回到顶部
题目大意:奶酪工厂在接下来N星期的单位奶酪成本价为C,所需订单奶酪为Y,奶酪工厂也可花费每周每单位S单价存储本周生产奶酪。 所以每周订单奶酪可由以前生产。问奶酪工厂这N周完成订单最小代价
贪心策略:每周订单寻找最小花费代价,即本周生产或者由以前生产。
#include <iostream>
#include <algorithm>
using namespace std;
int N, S;
typedef struct {
int c, y;
}Data;
Data d[10005];
int main() {
while(cin >> N >> S) {
for(int i = 0; i < N; i++) {
cin >> d[i].c >> d[i].y;
}
long long res = 0; //保存答案,题目提示int范围无法满足题目要求
res += 1L * d[0].c * d[0].y; //第一天只能当天生产
int min_pre = d[0].c; //保存以前每单位最低成本
for(int i = 1; i < N; i++) {
min_pre = min(min_pre+S, d[i].c); //找寻单位最小花费
res += 1L * min_pre * d[i].y; //加上本周代价
}
cout << res << endl;
}
return 0;
}
H_Packets 回到顶部
题目大意:输入6个数字表示6中底面积不同的各箱子个数,将所有箱子都打包到地底面积为66的箱子中(包括题目给出的66样式的箱子),最少需要多少箱子。所有箱子高度相同
贪心策略:此题感觉就写这比较麻烦,就尽可能多的装满每个箱子即可。
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
//输入
int a[6];
int main() {
while(true) {
int sum = 0;
for(int i = 0; i < 6; i++) {
cin >> a[i];
sum += a[i];
}
if(sum == 0) {
break;
}
int res = 0; //保存答案
//从大到小开始放箱子
//放6*6箱子
res += a[5]; //6*6箱子每个单独占用一个箱子
//放5*5的箱子:每个箱子可放一个5*5的箱子,再放入11个1*1的箱子
res += a[4];
a[0] -= min(a[0], a[4] * 11); //放入1*1的箱子
//放4*4的箱子:每个箱子可以放入一个4*4的箱子,还有5个2*2的空间
res += a[3];
int temp1 = a[3] * 5; //计算2*2空间个数
if(temp1 > a[1]) { //放2*2的箱子后有剩余空间
a[0] -= min(a[0], 4*(temp1-a[1]));
}
a[1] -= min(a[1], temp1); //放入2*2的箱子
//放3*3的箱子:每个箱子可以放4个3*3的盒子,每个3*3的盒子可以放1个2*2的盒子+5个1*1
res += ceil(a[2] / 4.0);
if(a[2] % 4 != 0) { //有剩余n个3*3的空间
temp1 = 4 - (a[2] % 4); //计算3*3空间个数
if(temp1 == 1) { //1个
a[1] -= min(a[1], temp1); //放入2*2的箱子
if(a[1] == 0) { //无2*2的箱子,放入1*1的箱子
a[0] -= min(a[0], temp1 * 9);
} else { //放入1个2*2的箱子后,放入1*1的箱子
a[0] -= min(a[0], 5);
}
}else if(temp1 == 2) { //2个3*3空间
int temp = min(a[1], 3); //2*2箱子最多放3个
a[1] -= temp; //放入2*2的箱子
a[0] -= min(a[0], (3-temp) * 4 + 6);
}else if(temp1 == 3) { //3个3*3空间
int temp = min(a[1], 5); //2*2的箱子最多放5个
a[1] -= temp; //放入2*2的箱子
a[0] -= min(a[0], (5-temp) * 4 + 7);
}
}
//2*2的箱子:每个6*6空间可放9个2*2的箱子
temp1 = ceil(a[1] / 9.0);
res += temp1; //放入2*2的箱子
if(a[1] % 9 != 0) { //有剩余空间
temp1 = a[1] % 9; //计算占用空间
a[0] -= min(a[0], 36 - temp1 * 4); //剩余空间放入1*1箱子
}
//放入1*1的箱子
temp1 = ceil(a[0] / 36.0);
res += temp1;
cout << res << endl;
}
return 0;
}
I_Allowance 回到顶部
题目大意:约翰有一套N个不同面值的钱币,面值为v的钱币有b张,约翰每周至少给Bessie C元钱币,问最多可以支付多少周
贪心策略:两种情况,1)当一张纸币面值足以支付时,直接支付。 2)当一张不足以支付时,用多张钱币凑足不少于C的钱币(此过程贪心,即每次凑币方案结果极可能接近C),
凑钱币的过程中应先尽可能的凑够C(可以小于等C,等不能超过C),然后再去凑满C(尽可能小的超过C,可以等于),即从小到大遍历
可能有多种凑币方式,即重复凑币的过程,直至完全找不到方案。
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int INF = 0x3f3f3f3f;
int N, C;
typedef struct {
int v, b;
}Data;
Data d[25];
bool cmp(Data d1, Data d2) {
//按面值从大到小排序
return d1.v > d2.v;
}
int main() {
while(cin >> N >> C) {
for(int i = 0; i < N; i++) {
cin >> d[i].v >> d[i].b;
}
sort(d, d+N, cmp);
int res = 0; //保存答案
int i = 0;
for(; i < N && d[i].v >= C; i++) { //面值大于等于零用钱的直接发放
res += d[i].b;
d[i].b = 0;
}
//面值不够零用钱的,多张钱币凑
while(true) {
vector<int> ans(25, 0); //ans[i]表示凑够一次零用钱第i张钱币被用几张
int temp = C; //表示当前还需多少钱凑够C
for(int j = i; j < N; j++) { //从大到小遍历,尽可能使钱币凑近C
while(ans[j] < d[j].b && temp-d[j].v >= 0) { //满足使用纸币个数不超过该纸币拥有个数,且尽可能靠近C,但不能超过C
ans[j]++;
temp -= d[j].v;
}
}
for(int j = N-1; j >= i; j--) { //从小到大遍历,凑足C,且付出当前最小代价,即超出C最小
while(ans[j] < d[j].b && temp > 0) { //满足使用纸币个数不超过该纸币拥有个数,且超出C尽可能小
ans[j]++;
temp -= d[j].v;
}
}
if(temp > 0) { //没有凑够C,无满足条件,退出
break;
}
//寻找当前钱币个数使用此种方法最多可凑多少套
int min_ans = INF;
for(int j = i; j < N; j++){
if(ans[j] != 0) {
min_ans = min(d[j].b/ans[j], min_ans);
}
}
res += min_ans;
//更新剩余钱币剩余个数
for(int j = i; j < N; j++) {
d[j].b -= ans[j] * min_ans;
}
}
cout << res << endl;
}
return 0;
}
J_ Stripies 回到顶部
此题提交G++与C++区分,该代码为C++代码
题目大意:有种生物可以两两合并,合并后的重量为 2sqrt(m1*m2),给N个生物的体重,求合并成1个生物后的体重
贪心策略:数字越大,开平方减去部分越多,即每次让最重与次重合并
#include <iostream>
#include <cstdio>
#include <queue>
#include <cmath>
using namespace std;
int N;
double a;
int main() {
while(cin >> N) {
priority_queue<double> que; //大根堆,队首位最大值
for(int i = 0; i < N; i++) {
cin >> a;
que.push(a);
}
while(que.size() > 1) {
//每次去最重合次重动物,组合
double t1 = que.top();
que.pop();
double t2 = que.top();
que.pop();
double temp = 2 * sqrt(t1 * t2); //合并
que.push(temp);
}
double res = que.top();
printf("%.3lf\n", res);
}
return 0;
}
K_Protecting the Flowers 回到顶部
题目大意:有N头牛每分钟吃d[i]朵花,农夫把每头牛送回牛舍需要花费2*t[i]时间(来回),求送完所有牛后,最少吃类多少花朵
贪心策略:不难想到每次运的牛为破坏的花朵最多的牛,即按照单位时间吃花量排序。
#include <iostream>
#include <algorithm>
using namespace std;
//输入
int N;
typedef struct {
int t, d;
}Data;
Data d[100005];
bool cmp(Data d1, Data d2) {
//按照运送时间内吃的花朵数量从大到小排序
/*
d1:2*d1.t*d2.d 先运送d1
d2:2*d2.t*d1.d 先运送d2
return 2 * d1.t * d2.d < 2* d2.t * d1.d
*/
return d1.t / (1.0 * d1.d) < d2.t / (1.0 * d2.d);
}
int main() {
while(cin >> N) {
for(int i = 0; i < N; i++) {
cin >> d[i].t >> d[i].d;
}
sort(d, d+N, cmp);
long long res = 0L; //保存答案
int time = 0; //保存当前运送牛已花费时间
for(int i = 0; i < N; i++) { //先运送吃花朵多的牛
res += 1L * time * d[i].d;
time += 2 * d[i].t;
}
cout << res << endl;
}
return 0;
}