hdu 2474 Process scheduling(模拟+队列)

http://acm.hdu.edu.cn/showproblem.php?pid=2474

题意:有n个资源和m个进程,先给出一个n*m的资源分配表,再给出一个n*m的资源需求表,request[i][j]表示第j个进程还需要i中资源request[i][j]个。最后给出一个m数的序列,available[i]表示第i种资源可用的数目。问是否存在一个合适的进程序列使得n个进程都能执行完毕。


思路:比赛时先是纯模拟了一遍,傻X了,n<=50000。然后队友提示说弄两个队列,在当前队列里遍历进程,若当前进程可以执行就标记,否则就近进一个队列等待判断。结果TLE。

可以这么想,因为m<=3,可以将m种资源分别放在m个队列中,开始将n个进程每种资源的request放进对应优先队列中。一个进程要执行成功,要有m种资源,即该进程要出队m次,每出队一次,说明该资源可供当前进程使用。所以只需判断进程是否出队m次即可。

#include <iostream>
#include <string>
#include <cmath>
#include <math.h>
#include <queue>
#include <algorithm>
#include <stack>
#include <vector>
#include <string.h>
#include <stdio.h>
using namespace std;

struct node
{
	int id;
	int need;
	bool operator < (struct node tmp)const
	{
		return need < tmp.need;
	}

}que[4][50010];

int n,m;
int allo[4][50010];
int ava[4];
int outque[50010];//记录每个进程出队列的次数
int p[4];

bool solve()
{
	int flag = 1;
	int i,j,k;
	int sum = 0;

	while(flag == 1) 
	{
		flag = 0;
		for(i = 1; i <= m; i++) //从第一个队列开始枚举
		{
			for( ; p[i] <= n; p[i]++)
			{
				if(ava[i] < que[i][p[i]].need)
					break;

				flag = 1;
				outque[ que[i][p[i]].id ]++; 
 				if(outque[ que[i][p[i]].id ] == m) //当出队次数等于m时,说明该进程可以执行
				{
					sum++;
					for(j = 1; j <= m; j++) //更新vav[]。
						ava[j] += allo[j][ que[i][p[i]].id ];
				}
			}
		}
	}

	if(sum == n)
		return true;
	return false;
}

void debug()
{
	for(int i = 1; i <= m; i++)
	{
		for(int j = 1; j <= n; j++)
			printf("i :%d need: %d ",que[i][j].id,que[i][j].need);
		printf("\n");
	}
}

int main()
{
	while(~scanf("%d %d",&n,&m))
	{
		for(int i = 1; i <= m; i++)
			for(int j = 1; j <= n; j++)
				scanf("%d",&allo[i][j]);

		for(int i = 1; i <= m; i++)
		{
			for(int j = 1; j <= n; j++)
			{
				que[i][j].id = j;
				scanf("%d",&que[i][j].need); //先把每个进程对应的m个资源放进队列
			}
		}
		
		//debug();
		for(int i = 1; i <= m; i++)
		{
			scanf("%d",&ava[i]);
			p[i] = 1;
			sort(que[i]+1,que[i]+1+n); //对每种资源按需求量升序排序
		}
		//debug();
		memset(outque,0,sizeof(outque)); 

		if(solve())
			printf("Yes\n");
		else printf("No\n");
	}
	return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于HDU4546问,还可以使用优先队列(Priority Queue)来解决。以下是使用优先队列的解法思路: 1. 首先,将数组a进行排序,以便后续处理。 2. 创建一个优先队列(最小堆),用于存储组合之和的候选值。 3. 初始化优先队列,将初始情况(即前0个数的组合之和)加入队列。 4. 开始从1到n遍历数组a的元素,对于每个元素a[i],将当前队列中的所有候选值取出,分别加上a[i],然后再将加和的结果作为新的候选值加入队列。 5. 重复步骤4直到遍历完所有元素。 6. 当队列的大小超过k时,将队列中的最小值弹出。 7. 最后,队列中的所有候选值之和即为前k小的组合之和。 以下是使用优先队列解决HDU4546问的代码示例: ```cpp #include <iostream> #include <vector> #include <queue> #include <functional> using namespace std; int main() { int n, k; cin >> n >> k; vector<int> a(n); for (int i = 0; i < n; i++) { cin >> a[i]; } sort(a.begin(), a.end()); // 对数组a进行排序 priority_queue<long long, vector<long long>, greater<long long>> pq; // 最小堆 pq.push(0); // 初始情况,前0个数的组合之和为0 for (int i = 0; i < n; i++) { long long num = pq.top(); // 取出当前队列中的最小值 pq.pop(); for (int j = i + 1; j <= n; j++) { pq.push(num + a[i]); // 将所有加和结果作为新的候选值加入队列 num += a[i]; } if (pq.size() > k) { pq.pop(); // 当队列大小超过k时,弹出最小值 } } long long sum = 0; while (!pq.empty()) { sum += pq.top(); // 求队列中所有候选值之和 pq.pop(); } cout << sum << endl; return 0; } ``` 使用优先队列的方法可以有效地找到前k小的组合之和,时间复杂度为O(nklog(k))。希望这个解法对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值