贪心 2016.10.25

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|1

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 = 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|1

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值