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


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