(06-06)思維的體操

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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章