poj 1827 A Bunch Of Monsters

 Poj 1827 http://poj.org/problem?id=1827

题意

游戏描述为:
1。 有许多箱财宝,编号从1到x一盒只有一个号码,一个号码只能出现在一个盒子里。 此外,我们可以假设X是无穷大,
2。 在这个游戏中有N个怪物。 每一个随机拿起一张卡片。 之后,他/她 打开它(?),得到一个正整数维数d[i], 他就并不能改变它或拿起另一个卡了。 d[i]的范围从1到m .如果第i个怪物数量d[i],他只能获得宝箱编号只能等于或小于d[i]。 更重要的是,一个盒子只能分配给一个怪物,怪物只能得到一个盒子。
3。,他也知道,怪物没有获得箱子 就会惩罚他。
吉姆知道N怪物的力量强度。 第i个有力量s[i]。你的任务是帮助吉姆找到最低伤害。

输入 第一行,两个数,N 怪物数量, M 箱子表编号范围 ,下行,N个数,怪物拿起卡片编号,在下一行,N个,怪物的力量

看似简单的题目,却用到并查集,如果使用标记,在一个一个查找,会 TLE  ,还是并查集高效,A 了一个下午,还是百度给力啊大哭

同时,这一题,复习了结构体的定义,结构体的sort排序。。

并查集的代码:

#include<iostream>
#include<algorithm>
#include<stdio.h>
using namespace std ;
const int N = 50001 ;
struct Node
{
	int d, s;
} mons[N];
int   n, m, p[N];
int   cmp(Node a, Node b)
{
	if (a.s != b.s)
	{
		return a.s > b.s ;
	}

	return a.d > b.d ;
}
int   find(int x)
{
	if (x != p[x])
	{
		p[x] = find(p[x]) ;
	}

	return p[x] ;
}
void  Un_set(int x, int y)
{
	int rx = find(x) , ry = find(y) ;
	p[ry] = p[rx] ;
	//printf("p[%d] = p[%d]\n",rx,ry);
}
int   main()
{
	while (~scanf("%d%d", &n, &m) && (n + m))
	{
		for (int i = 1; i <= n; i++)
		{
			scanf("%d", &mons[i].d) ;
		}

		for (int i = 1; i <= n; i++)
		{
			scanf("%d", &mons[i].s) ;
		}

		sort(mons + 1, mons + n + 1, cmp);

		for (int i = 0; i <= m; i++)
		{
			p[i] = i ;
		}

		int sum = 0 ;

		for (int i = 1; i <= n; i++)
		{
			int rd = find(mons[i].d);

			//printf("find(mons[i].d = %d) = %d\n",mons[i].d,rd);

			if (rd == 0)
			{
				//printf("s = %d\n", mons[i].s);
				sum += mons[i].s ;
				continue ;
			}

			Un_set(rd - 1, mons[i].d);
		}

		printf("%d\n", sum);
	}

	return 0 ;
}

自己的标记,查找代码,效率低,还是错误的。。。。。。。

#include<stdio.h>
#include<algorithm>
using namespace std;
int bleg[50005] = {0};
typedef struct mon
{
	int s;
	int d;
}mon;
bool cmp(mon mon1,mon mon2)
{
	if(mon1.s < mon2.s) return mon1.s > mon2.s;
	else if(mon1.s == mon2.s) return mon1.d>mon2.d;
}
int main()
{
	mon mon[50005];
	int n,m,i;
	while(~scanf("%d %d",&n,&m) && m+n!=0)
	{
		bleg[0] = 1;
		int sum = 0;
		for(i=1;i<=n;i++)
		{
			scanf("%d",&mon[i].d);
		}
		for(i=1;i<=n;i++)
		{
			scanf("%d",&mon[i].s);
		}
		sort(mon+1,mon+n+1,cmp);
		//for(i=1;i<n;i++) printf("%d %d\n",mon[i].d,mon[i].s);
		//printf("\n");
		for(i = 1;i<=n;i++)
		{
			int k = 0;
			if(mon[i].d>m) sum += mon[i].s;
			else if(bleg[mon[i].d] == 0)
			{
				bleg[mon[i].d] = 1;
			}
			else
			{
				k = 0;
				//printf("jin er %d\n",mon[i].d);
				while(bleg[mon[i].d-k]!=0)
				{
					//printf("jin san %d\n",mon[i].d);
					//printf("xiangjianhou%d\n",mon[i].d - k);
					if(mon[i].d - k == 0)
					{
						//printf("%d %d\n",mon[i].d,k);
						sum+=mon[i].s;
						break;
					}
					k++;
				}
				//printf("chulai%d\n",mon[i].d - k);
				bleg[mon[i].d-k] = 1;
			}
		}
		printf("%d\n",sum);
	}
}

这个的查找代码是正确的

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
using namespace std;
typedef struct mon
{
	int s;
	int d;
}mon;
int cmp( const void *a , const void *b )
{
	mon	*c = (mon *)a;
	mon *e = (mon *)b;
	if(c->s != e->s) return e->s - c->s;
	else return e->d - c->d;
}
int main()
{
	mon mn[50005];
	int n,m,i;
	while(~scanf("%d %d",&n,&m) && m+n!=0)
	{
		int bleg[50005] = {0};
		memset(&mn,0,sizeof(mon));
		bleg[0] = 1;
		int sum = 0;
		for(i=0;i<n;i++)
		{
			scanf("%d",&mn[i].d);
		}
		for(i=0;i<n;i++)
		{
			scanf("%d",&mn[i].s);
		}

		qsort(mn,n,sizeof(mon),cmp);
/*
		for(i=0;i<n;i++) printf("%d %d\n",mn[i].d,mn[i].s);
		printf("\n");
*/
		for(i = 0;i<n;i++)
		{
			int k = 0;
			if(mn[i].d > m)  sum += mn[i].s;

			else if(bleg[mn[i].d] == 0)
			{
				bleg[mn[i].d] = 1;
			}

			else
			{
				int k ,t = 0;
				for(k = mn[i].d; k>0; k--)
				{
					if(bleg[k] == 0)
					{
						bleg[k] = 1;
						t = 1;
						break;
					}
					if(bleg[k-1] == 0)
					{
						bleg[k-1] = 1;
						t = 1;
						break;
					}
					k = k - 1;
				}
				if(t==0)
				{
					sum += mn[i].s;
					//printf("mn[%d] = %d\n",i,mn[i].s);
				}
			}
		}
		printf("%d\n",sum);
	}
}
/*
7 7
6 4 4 2 4 3 4
10 70 20 60 30 50 40
*/


转载于:https://www.cnblogs.com/tenlee/p/4420161.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值