贪心 2016.10.25

来源:互联网 发布:c语言实验时间格式转换 编辑:程序博客网 时间:2024/05/16 17:38

1、HDU 5821 Ball

solution by 学军中学

假设有4个红球,初始时从左到右标为1,2,3,4。那么肯定存在一种方案,使得最后结束时红球的顺序没有改变,也是1,2,3,4。那么就可以把同色球都写成若干个不同色球了

所以现在共有n个颜色互异的球。按照最终情况标上1,2,。。,n的序号,那么贪心的来每次操作就是把一个区间排序就行了

#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <queue>#include <vector>#include <stack>#include <map>#include <cmath>#include <cctype>#include <bitset>using namespace std;typedef long long ll;typedef unsigned long long ull;typedef unsigned int uint;typedef pair<int, int> Pair;const ull mod = 1e9 + 7;const int INF = 0x7fffffff;const int maxn = 1e3 + 10;int a[maxn];int n, m;int vis[maxn];int main(){#ifdef __AiR_H    freopen("in.txt", "r", stdin);#endif // __AiR_H    int t;    scanf("%d", &t);    while (t--) {        queue<int> Q[maxn];        scanf("%d %d", &n, &m);        memset(vis, 0, sizeof(vis));        bool flag = true;        for (int i = 1; i <= n; ++i) {            scanf("%d", &a[i]);            ++vis[a[i]];        }        int b;        for (int i = 1; i <= n; ++i) {            scanf("%d", &b);            --vis[b];            Q[b].push(i);        }        for (int i = 1; i <= n; ++i) {            if (vis[i] != 0) {                flag = false;                break;            }        }        if (flag) {            for (int i = 1; i <= n; ++i) {                int t = a[i];                a[i] = Q[t].front();                Q[t].pop();            }        }        int l, r;        while (m--) {            scanf("%d %d", &l, &r);            if (flag) {                sort(a+l, a+r+1);            }        }        for (int i = 1; i <= n; ++i) {            if (a[i] != i) {                flag = false;                break;            }        }        if (flag) {            printf("Yes\n");        } else {            printf("No\n");        }    }    return 0;}


2、XTU 1252 Defense Tower


解题思路:

按照攻击力从大到小进行破坏,所以当我们破坏某个防御塔的时候,攻击力小于它的防御塔必然没有被破坏

#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <queue>#include <vector>#include <stack>#include <map>#include <cmath>using namespace std;typedef long long ll;typedef unsigned long long ull;typedef unsigned int uint;const int mod = 1e9 + 7;const int INF = 0x7fffffff;const int maxn = 1e5 + 10;int n;int power[maxn];int main(){    while (scanf("%d", &n) != EOF) {        for (int i = 1; i <= n; ++i) {            scanf("%d", &power[i]);        }        int ans = 0;        int a, b;        for (int i = 0; i < n-1; ++i) {            scanf("%d%d", &a, &b);            ans += min(power[a], power[b]);        }        printf("%d\n", ans);    }    return 0;}

3、Codeforces 527D Clique Problem

参考:http://www.cnblogs.com/qzqzgfy/p/5627186.html

题意:

给出一些点的 xi 和 wi,当 |xi − xj| ≥ wi+wj 的时候,两点间存在一条边,找出一个最大的集合,集合中的点两两之间存在边

解题思路:

若 |xi - xj| ≥ wi + wj

可能有 xi - xj ≥ wi + wj 或 xj - xi ≥ wi + wj 两种情况

那么有 wj + xj ≤ xi - wi 或 wi + xi ≤ xj - wj

所以将这些点按照 w + x 排序后,从最小的到最大的贪心连边,就可以保证这些点两两之间存在边


#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <queue>#include <vector>#include <stack>#include <map>#include <set>#include <cmath>#include <cctype>#include <bitset>#include <ctime>using namespace std;#define REP(i, n) for (int i = 0; i < (n); ++i)#define lson low, mid, _id<<1#define rson mid+1, high, _id<<1|1typedef long long ll;typedef unsigned long long ull;typedef unsigned int uint;typedef pair<int, int> Pair;const ull mod = 1e9 + 7;const int INF = 0x7fffffff;const int maxn = 2e5 + 10;struct Node {    int x, w;    bool operator < (Node a) {        return x+w < a.x+a.w;    }};int n;Node node[maxn];int main(){#ifdef __AiR_H    freopen("in.txt", "r", stdin);#endif // __AiR_H    scanf("%d", &n);    for (int i = 0; i < n; ++i) {        scanf("%d %d", &node[i].x, &node[i].w);    }    sort(node, node+n);    int t = node[0].w + node[0].x, ans = 0;    for (int i = 1; i < n; ++i) {        if (t <= node[i].x - node[i].w) {            ++ans;            t = node[i].x + node[i].w;        }    }    printf("%d\n", ans+1);    return 0;}


4、Codeforces 383A Milking cows

解题思路:

先从右到左给面朝左的奶牛挤奶,然后再从左到右给面朝右的奶牛挤奶

#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <queue>#include <vector>#include <stack>#include <map>#include <set>#include <cmath>#include <cctype>#include <bitset>#include <ctime>using namespace std;#define REP(i, n) for (int i = 0; i < (n); ++i)#define lson low, mid, _id<<1#define rson mid+1, high, _id<<1|1typedef long long ll;typedef unsigned long long ull;typedef unsigned int uint;typedef pair<int, int> Pair;const ll mod = 1e9 + 7;const int INF = 0x7fffffff;const int maxn = 2e5 + 10;ll n;ll a[maxn], sum[maxn];int main(){#ifdef __AiR_H    freopen("in.txt", "r", stdin);#endif // __AiR_H    scanf("%I64d", &n);    for (ll i = 1; i <= n; ++i) {        scanf("%I64d", &a[i]);        sum[i] = sum[i-1] + a[i];    }    ll ans = 0;    for (ll i = n; i >= 1; --i) {        if (a[i] == 0) {            ans += sum[i];        }    }    printf("%I64d\n", ans);    return 0;}


5、2016-2017 ACM-ICPC, NEERC, Southern Subregional Contest (Online Mirror, ACM-ICPC Rules, Teams Preferred)  A Toda 2

解题思路:

按情况每次减 3 或者减 2

例如 1 4 4 4 这种情况就需要减 3

在队友代码基础上 xjb 改了改,感觉压行还好吧...


#include<cstdio>#include<algorithm>#include <queue>using namespace std;const int INF = 0x7fffffff;int s[10005][10005];struct node{int id;int num;bool operator < (const node &b)const{return num < b.num;}}a[105];int Min = INF, sum = 0;priority_queue<node> Queue;int main(){int n,i,k,j;scanf("%d", &n);for(i = 0; i < n; i++){scanf("%d", &a[i].num);        sum += a[i].num;if (a[i].num < Min) {Min = a[i].num;}a[i].id = i;Queue.push(a[i]);}k = 0;while(1){node f1 = Queue.top(), f2, f3;if (f1.num == Min) {break;}if (Queue.size() >= 4 && (sum - Min * Queue.size()) % 2 == 1) {            Queue.pop(), f2 = Queue.top(), Queue.pop(), f3 = Queue.top(), Queue.pop();            if (f1.num > 0) --f1.num, --sum;            if (f2.num > 0) --f2.num, --sum;            if (f3.num > 0) --f3.num, --sum;            if (Min > f1.num) Min = f1.num;            if (Min > f2.num) Min = f2.num;            if (Min > f3.num) Min = f3.num;            Queue.push(f1), Queue.push(f2), Queue.push(f3);            for(i = 0; i < n; i++) s[k][i] = ((i == f1.id || i == f2.id || i == f3.id) ? 1 : 0);} else {            Queue.pop(), f2 = Queue.top(), Queue.pop();            if (f1.num > 0) --f1.num, --sum;            if (f2.num > 0) --f2.num, --sum;            if (Min > f1.num) Min = f1.num;            if (Min > f2.num) Min = f2.num;            Queue.push(f1), Queue.push(f2);            for(i = 0; i < n; i++) s[k][i] = ((i == f1.id || i == f2.id) ? 1 : 0);}k++;}printf("%d\n", Min);printf("%d\n", k);for(i = 0; i < k; i++){for(j = 0; j < n; j++)printf("%d", s[i][j]);printf("\n");}return 0;}


0 0