算法課複習 -- 貪心

HDU #1863 : 暢通工程

傳送門:http://acm.hdu.edu.cn/showproblem.php?pid=1863

題意:有n個點和m條權值邊,問將整個圖連通最少需要花費多少。

思路:最小生成樹。

AC代碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<utility>
#include<algorithm>
#include<utility>
#include<queue>
#include<vector>
#include<set>
#include<stack>
#include<cmath>
#include<map>
#include<ctime>
#include<functional>
#include<bitset>
#define P pair<int,int>
#define ll long long
#define ull unsigned long long
#define lson id*2,l,mid
#define rson id*2+1,mid+1,r
#define ls id*2
#define rs (id*2+1)
#define Mod(a,b) a<b?a:a%b+b
#define cl0(a) memset(a,0,sizeof(a))
#define cl1(a) memset(a,-1,sizeof(a))
using namespace std;

const ll M = 1e9 + 7;
const ll INF = 1e9;
const double _e = 10e-6;
const int maxn = 1e2 + 10;
const int matSize = 9;
const int dx[4] = { 0,0,1,-1 }, dy[4] = { 1,-1,0,0 };
const int _dx[8] = { -1,-1,-1,0,0,1,1,1 }, _dy[8] = { -1,0,1,-1,1,-1,0,1 };

int x, y, z;
char c;

struct node
{
	int to;
	int cost;
};

int m, n, cnt;
bool used[maxn];
vector<node> edge[maxn];

struct cmp
{
	bool operator()(node a, node b)
	{
		return a.cost > b.cost;
	}
};

void init()
{
	cnt = 0;
	cl0(used);
	for (int i = 1; i <= n; i++)
		edge[i].clear();
}

int main()
{
	while (~scanf("%d%d", &m, &n)) {
		if (m == 0)break;
		init();
		int aa, bb, cc; cc = INF;
		for (int i = 1; i <= m; i++) {
			scanf("%d%d%d", &x, &y, &z);
			edge[x].push_back(node{ y,z });
			edge[y].push_back(node{ x,z });
			if (z < cc) {
				cc = z; aa = x; bb = y;
			}
		}
		used[aa] = true; used[bb] = true;
		priority_queue<node, vector<node>, cmp> que;
		for (int i = 0; i < edge[aa].size(); i++) 
			que.push(edge[aa][i]);
		for (int i = 0; i < edge[bb].size(); i++)
			que.push(edge[bb][i]);
		int now = 2, ans = cc;
		while (now < n && !que.empty()) {
			node u = que.top(); que.pop();
			if (!used[u.to]) {
				now++;
				used[u.to] = true;
				ans += u.cost;
				for (int i = 0; i < edge[u.to].size(); i++)
					que.push(edge[u.to][i]);
			}
		}
		if (now != n)
			puts("?");
		else
			printf("%d\n", ans);
	}	
	return 0;
}

 

HDU #1053 : Entropy

傳送門:http://acm.hdu.edu.cn/showproblem.php?pid=1053

題意:給一個字符串,問最少需要多少位就可以將它編碼。

思路:Huffman編碼。優先隊列,每次把最小的兩塊拿出來相加再塞回隊列,隊列裏最後一個元素就是答案。

AC代碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<utility>
#include<algorithm>
#include<utility>
#include<queue>
#include<vector>
#include<set>
#include<stack>
#include<cmath>
#include<map>
#include<ctime>
#include<functional>
#include<bitset>
#define P pair<int,int>
#define ll long long
#define ull unsigned long long
#define lson id*2,l,mid
#define rson id*2+1,mid+1,r
#define ls id*2
#define rs (id*2+1)
#define Mod(a,b) a<b?a:a%b+b
#define cl0(a) memset(a,0,sizeof(a))
#define cl1(a) memset(a,-1,sizeof(a))
using namespace std;

const ll M = 1e9 + 7;
const ll INF = 1e9;
const double _e = 10e-6;
const int maxn = 1e5 + 10;
const int matSize = 9;
const int dx[4] = { 0,0,1,-1 }, dy[4] = { 1,-1,0,0 };
const int _dx[8] = { -1,-1,-1,0,0,1,1,1 }, _dy[8] = { -1,0,1,-1,1,-1,0,1 };

int x, y, z;
char c;

int now;
string str;
int cnt[30];
map<char, int> mp;

void init()
{
	mp.clear();
	cl0(cnt);
	now = 0;
}

struct cmp
{
	bool operator()(int a, int b)
	{
		return a > b;
	}
};

int main()
{
	while (cin >> str) {
		if (str == "END")break;
		init();
		int len = str.length();
		for (int i = 0; i < len; i++) {
			if (mp[str[i]] == 0)
				mp[str[i]] = ++now;
			cnt[mp[str[i]]]++;
		}
		priority_queue<int, vector<int>, cmp> que;
		int ans = 0;
		for (int i = 1; i <= now; i++)
			que.push(cnt[i]);
		if (que.size() == 1)
			ans = cnt[1];
		else {
			while (que.size() > 1) {
				int a = que.top(); que.pop();
				int b = que.top(); que.pop();
				que.push(a + b);
				ans += a + b;
			}
		}
		printf("%d %d %.1f\n", len * 8, ans, (double)len * 8 / ans);
	}
	return 0;
}

 

HDU #2021 : 發工資咯:)

傳送門:http://acm.hdu.edu.cn/showproblem.php?pid=2021

題意:將正整數n表示爲若干個100、50、10、5、2和1的和,問最少需要多少個。

思路:因爲對於每兩個值a、b(a>b)都有a>=2b,所以直接貪心即可。

AC代碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<utility>
#include<algorithm>
#include<utility>
#include<queue>
#include<vector>
#include<set>
#include<stack>
#include<cmath>
#include<map>
#include<ctime>
#include<functional>
#include<bitset>
#define P pair<int,int>
#define ll long long
#define ull unsigned long long
#define lson id*2,l,mid
#define rson id*2+1,mid+1,r
#define ls id*2
#define rs (id*2+1)
#define Mod(a,b) a<b?a:a%b+b
#define cl0(a) memset(a,0,sizeof(a))
#define cl1(a) memset(a,-1,sizeof(a))
using namespace std;

const ll M = 1e9 + 7;
const ll INF = 1e9;
const double _e = 10e-6;
const int maxn = 1e2 + 10;
const int matSize = 9;
const int dx[4] = { 0,0,1,-1 }, dy[4] = { 1,-1,0,0 };
const int _dx[8] = { -1,-1,-1,0,0,1,1,1 }, _dy[8] = { -1,0,1,-1,1,-1,0,1 };

int x, y, z;
char c;

int n, m;
int a[6] = { 100,50,10,5,2,1 };

int main()
{
	while (~scanf("%d", &n)) {
		if (n == 0)break;
		int ans = 0;
		while (n--) {
			scanf("%d", &m);
			for (int i = 0; i < 6; i++) {
				ans += m / a[i];
				m %= a[i];
			}
		}
		printf("%d\n", ans);
	}	
	return 0;
}

 

HDU #4221 : Greedy?

傳送門:http://acm.hdu.edu.cn/showproblem.php?pid=4221

題意:有n件事,每件事有完成所需時間c,並且應該在時間d前完成。問所有事最少超時之和爲多久。

思路:按d從小到大排列按順序完成,累加時間就是答案。

AC代碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<utility>
#include<algorithm>
#include<utility>
#include<queue>
#include<vector>
#include<set>
#include<stack>
#include<cmath>
#include<map>
#include<ctime>
#include<functional>
#include<bitset>
#define P pair<int,int>
#define ll long long
#define ull unsigned long long
#define lson id*2,l,mid
#define rson id*2+1,mid+1,r
#define ls id*2
#define rs (id*2+1)
#define Mod(a,b) a<b?a:a%b+b
#define cl0(a) memset(a,0,sizeof(a))
#define cl1(a) memset(a,-1,sizeof(a))
using namespace std;

const ll M = 1e9 + 7;
const ll INF = 1e9;
const double _e = 10e-6;
const int maxn = 1e5 + 10;
const int matSize = 9;
const int dx[4] = { 0,0,1,-1 }, dy[4] = { 1,-1,0,0 };
const int _dx[8] = { -1,-1,-1,0,0,1,1,1 }, _dy[8] = { -1,0,1,-1,1,-1,0,1 };

int x, y, z;
char c;

struct node
{
	ll c, d;
};

int n, m;
node a[maxn];

bool cmp(node a, node b)
{
	return a.d < b.d;
}

int main()
{
	int t;
	scanf("%d", &t);
	for (int _ = 1; _ <= t; _++) {
		ll ans = 0;
		scanf("%d", &n);
		for (int i = 1; i <= n; i++)
			scanf("%lld%lld", &a[i].c, &a[i].d);
		sort(a + 1, a + n + 1, cmp);
		ll now = 0;
		for (int i = 1; i <= n; i++) {
			now += a[i].c;
			ans = max(ans, now - a[i].d);
		}
		printf("Case %d: %lld\n", _, ans);
	}
	return 0;
}

 

HYSBZ #1826 : 緩存交換

傳送門:https://www.lydsy.com/JudgeOnline/problem.php?id=1826

題意:cache調度,按順序給出n個內存塊。問怎麼調度miss最少。

思路:當cache滿時,如果miss發生就將cache中在之後最晚再出現的塊踢掉。

優先隊列,記錄內存塊編號及它下一次出現的時間,如果再也不出現時間就爲INF,按照下次時間從大到小排。

由於n<=1e5,但內存塊編號<=1e9,可以用map來搞。

AC代碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<utility>
#include<algorithm>
#include<utility>
#include<queue>
#include<vector>
#include<set>
#include<stack>
#include<cmath>
#include<map>
#include<ctime>
#include<functional>
#include<bitset>
#define P pair<int,int>
#define ll long long
#define ull unsigned long long
#define lson id*2,l,mid
#define rson id*2+1,mid+1,r
#define ls id*2
#define rs (id*2+1)
#define Mod(a,b) a<b?a:a%b+b
#define cl0(a) memset(a,0,sizeof(a))
#define cl1(a) memset(a,-1,sizeof(a))
using namespace std;

const ll M = 1e9 + 7;
const ll INF = 1e9 + 10;
const double _e = 10e-6;
const int maxn = 1e5 + 10;
const int matSize = 9;
const int dx[4] = { 0,0,1,-1 }, dy[4] = { 1,-1,0,0 };
const int _dx[8] = { -1,-1,-1,0,0,1,1,1 }, _dy[8] = { -1,0,1,-1,1,-1,0,1 };

int x, y, z;
char c;

int m, n, cnt;
int a[maxn];
map<int, int> mp;
bool used[maxn];

struct node
{
	int id;
	int nxt;
};

struct cmp
{
	bool operator()(node a, node b)
	{
		return a.nxt < b.nxt;
	}
};

int main()
{
	while (~scanf("%d%d", &n, &m)) {
		mp.clear(); cnt = 0; cl0(used);
		queue<int> nxt[maxn];
		for (int i = 1; i <= n; i++) {
			scanf("%d", &a[i]);
			if (mp[a[i]] == 0)
				mp[a[i]] = ++cnt;
			nxt[mp[a[i]]].push(i);
		}
		for (int i = 1; i <= cnt; i++)
			nxt[i].push(INF);
		priority_queue<node, vector<node>, cmp> que;
		int now = 0, ans = 0;
		for (int i = 1; i <= n; i++) {
			if (!used[mp[a[i]]]) {
				ans++; used[mp[a[i]]] = true;
				if (now != m) 
					now++;
				else {
					node u = que.top(); que.pop();
					used[u.id] = false;
				}
			}
			nxt[mp[a[i]]].pop();
			que.push(node{ mp[a[i]],nxt[mp[a[i]]].front() });
		}
		printf("%d\n", ans);
	}
	return 0;
}

 

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