1、Uva 11292 王者斗恶龙
分析:最少花费,找能砍掉恶龙投的最小雇佣骑士便可,贪心一下(可以分别两个全部从小到大排序,之后挨着砍),也可以训练一下优先队列
#include <cstdio>
#include <cstring>
#include <queue>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int n,m;
while (scanf("%d %d", &n, &m) && n)
{
priority_queue<int, vector<int>, greater<int> >Q1;//优先队列每次弹出最小值
priority_queue<int, vector<int>, greater<int> >Q2;
int cost = 0;
for (int i = 0; i < n; i++)
{
int a;
scanf("%d", &a);
Q1.push(a);
}
for (int i = 0; i < m; i++)
{
int a;
scanf("%d", &a);
Q2.push(a);
}
while (Q2.size())
{
if (Q1.empty()) break;
if (Q1.top() > Q2.top()) Q2.pop();
else {
cost += Q2.top();
Q2.pop();
Q1.pop();
}
}
if (Q1.size()) printf("Loowater is doomed!\n");
else printf("%d\n",cost);
}
return 0;
}
2、Uva 11729 突击战
分析:交待任务的时间是必须花费的,但交代任务的同时,已交代完任务的骑士可以执行任务,所以我们便可以贪心,执行时间较长的任务应该先交代
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
struct Node
{
int B,J;
}person[1005];
bool cmp(Node a, Node b){
return a.J > b.J;
}
int main()
{
int kase = 1;
priority_queue<int, vector<int>, greater<int> >Q1;
int n;
while (scanf("%d", &n) && n)
{
for (int i = 0; i < n; i++){
scanf("%d %d", &person[i].B, &person[i].J);
}
sort(person, person+n, cmp);//按照执行任务长短从大到小排列
int MaxTime = 0;
int s = 0;
for (int i = 0; i < n; i++){
s += person[i].B;
MaxTime = max(MaxTime, s + person[i].J);//更新任务完成的最长时间
}
printf("Case %d: %d\n", kase++, MaxTime);
}
return 0;
}
3、Uva11300 分金币
分析:这个题看起来很复杂,对,我是蒙的,完全没有头绪,经过看刘老师的书才豁然开朗,类似于一个递推关系。另外关于中位数的处理可谓精妙绝伦,学到了。。。
#include <cstdio>
#include <cstring>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
int A[1000005],C[10000005];
int main()
{
int n;
ll sum = 0;
while (scanf("%d", &n) == 1)
{
sum = 0;
for (int i = 1; i <= n; i++)
{
scanf("%d", &A[i]);
sum += A[i];
}
ll M = sum / n;
C[0] = 0;
for (int i = 1; i < n; i++) //递推求C【i】
C[i] = C[i-1] + A[i] -M;
sort(C, C+n);
ll x1 = C[n/2]; //当x1为C【i】中位数时,最小(可以自己证明一下)
ll ans = 0;
for (int i = 0; i<n; i++)
ans += abs(x1 - C[i]);
printf("%lld\n", ans);
}
return 0;
}
4、LA3708 墓地雕塑
分析:这是个看似水,其实还稍微有点技巧的题目
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
int main()
{
int n, m;
while (scanf("%d %d", &n, &m) != EOF)
{
double ans = 0.0;
for (int i = 1; i < n; i++)
{
double pos = i*1.0 / n*(n+m);//计算每个需要移动的雕塑的坐标
ans += fabs(pos - floor(pos+0.5)) / (n+m);//累加移动距离
}
printf("%.4f\n", ans*10000);//等比例扩大坐标
}
return 0;
}
5、Uva 10881 蚂蚁(这是POJ Ant问题的扩展版)
分析:POJ Ant的优化在于“掉头” 等价于 “”对穿而过,毕竟POJ Ant只需得出蚂蚁落下的最长和最短时间;但本题与此有区别,不知需要知道是否落下,还需知道最后每个蚂蚁的状态(位置, 移动方向(是否落下))这个题的做法也是非常精彩的
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 10005;
struct Ant
{
int id;//输入顺序
int p; //位置
int d; //朝向 -1 左 0 转身ing 1 右
bool operator <(const Ant &a)const{
return p < a.p;
} //重载<号
}before[maxn], after[maxn];
const char dirName[][10] = {"L", "Turning", "R"};
int order[maxn];
int main()
{
int t;
scanf("%d", &t);
for (int kase = 1; kase<=t; kase++)
{
printf("Case #%d:\n", kase);
int L, T, n;
scanf("%d %d %d",&L, &T, &n);
for (int i = 0; i<n; i++)
{
int p, d;
char c;
scanf("%d %c", &p, &c);
d = (c=='L'? -1 : 1);
before[i] = (Ant){i, p, d};
after[i] = (Ant){0, p+T*d, d};
}
sort(before, before+n);
for (int i = 0; i<n; i++)
order[before[i].id] = i;//按距左边的距离从小到大编号
sort(after, after+n);
for (int i = 0; i<n-1; i++)
if (after[i].p == after[i+1].p) after[i].d = after[i+1].d = 0;//判断是否会发生碰撞,修改碰撞方向
for (int i = 0; i<n; i++)
{
int a = order[i];
if (after[a].p <0 || after[a].p > L) printf("Fell off\n");
else printf("%d %s\n", after[a].p, dirName[after[a].d+1]);
}
printf("\n");
}
return 0;
}