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;
}
#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;
}