华农专业课拯救计划:ccf,csp题组训练第一周

1.202203 -1 未初始化警告

这道题虽然题目很绕,但是只有两个意思:

1.每个表达式的右值必须在式子出现之前被初始化

2.每个表达式的左值在表达式结束后被初始化

题目的目的也很简单:找到所有不符合题意1的右值数量

思路:哈希表,对于每个式子,先判断右值是否在哈希表里,再给左值赋值

#include<bits/stdc++.h>
using namespace std;

int main(){
	int n, k,cnt=0; 
	cin>>n>>k;
	int hash[n+1] = {0}; 
	hash[0] = 1;
	for(int i = 0 ; i < k; i++){
		int a , b;
		cin>>a>>b;
		if(hash[b] == 0){   
			cnt++;
			hash[a] = 1;
		}
		else if(hash[b] == 1){ 
			hash[a] = 1;
		}
	}
	cout<<cnt;
}
 2.202203-2  出行计划 
        

 题目很简单,但是要理清楚先后顺序,不要被输入顺序牵着逻辑走,这里分享一下我的逻辑顺序,首先是m次查询,也就是起点,去做核酸,然后等待wait的时间,此时拥有了核酸检测报告。然后是时间和要求,必须在某个时间段,具有一份规定时间内做的核酸检测报告,这样有效的里程+1

首先是90分的简单模拟(就是有兴趣的看一下,别复制错了)

#include<vector>
using namespace std;
int main()
{
	vector<int>time;
	vector<int>limit;
	int num, sign, wait;
	cin >> num >> sign >> wait;
	vector<int>done;
	vector<int>ret;
	for (int i = 0; i < num; i++)
	{
		int a, b;
		cin >> a >> b;
		time.push_back(a);
		limit.push_back(b);
	}
	for (int i = 0; i < sign; i++)
	{
		int t;
		cin >> t;
		done.push_back(t);
	}
	for (auto l : done)
	{
		int gettime = l + wait;
		int count = 0;
		for (int i = 0; i < num; i++)
		{
			if (gettime <= time[i] && gettime + limit[i] > time[i])
			{
				count++;
			}

		}
		cout<<count<<endl;
	}

	return 0;
}

为啥模拟能拿90分?虽然说枚举胜标算,暴力破百万,但为啥这么夸张?

首先是vector,比定长数组更快,花费空间更小,还有范围for的使用,也间接提速了

其次是满分的前缀和(我也不太确定这个叫啥,反正不是纯种的前缀和,但绝对算动态规划的范畴)(复制这个)

逻辑也很简单,首先将每次查询搞出来一个获得核酸报告的时间,然后做一个ret数组,利用每次行程的有效期去更新数组,dp[i]表示在i时间有几个行程可以选择,此外,注意一些细节即可

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
	vector<int>time;
	vector<int>limit;
	int num, sign, wait;
	cin >> num >> sign >> wait;
	vector<int>done;
	
	int a, b;
  
	for (int i = 0; i < num; i++)
	{
		
		cin >> a >> b;
        
		time.push_back(a);
		limit.push_back(b);
	}
	vector<int>ret(a+1000);
	for (int i = 0; i < num; i++)
	{
		int r=time[i];
		int l = time[i] - limit[i] + 1;
		for (int j = r; j > 0 && j >= l; j--)
		{
			ret[j]++;
		}
	}
	for (int i = 0; i < sign; i++)
	{
		int t;
		cin >> t;
		t = t + wait;
		cout << ret[t] << endl;
	}
	return 0;
}
3.202203 -3 计算资源调度器

 

 

眼前一黑......题目也太长了吧?不过,基于高中做理综大题的经验,题目越长,题目越简单(吗),我看了好几遍才理解了题意

首先要理清题目中的关系,一个应用有多个计算任务,不同的计算任务要在一些计算区域上进行,可能对区域或者区域中的应用有要求,现在要解决这些要求

其次, 要确定存储结构

这就要有一个数组存储着任务与区域的关系,以便验证对应关系

这就要用一个二维vector(后来用了set去重,一个道理)来存储应用以及这个应用所在的区域

和上一个同理

接下来是判断逻辑

这就说明过度有两个阶段:

1.找出符合全部要求的点

2.1失败了,在paari允许的情况下,找出符合1,2的点

 告诉我们要有一个存储结构来存储不同计算节点的任务数

接下来是完整代码(复制)

#include<iostream>
#include<vector>
#include<unordered_map>
#include<unordered_set>
#include<set>
#include<cmath>
#include<algorithm>
using namespace std;
int signnum[1020] = { 0 };
unordered_map<int, unordered_set<int>>app;
unordered_map<int, int>tasknum;
bool signqinghe(int sign, int pos)
{
	return sign == 0 || signnum[pos] == sign;
}
bool missonqinghe(int apply, int pos)
{
	if (apply == 0)
	{
		return true;
	}
	int signpos = signnum[pos];
	for (auto l : app[apply])
	{
		if (signpos == signnum[l])
		{
			return true;
		}
	}
	return false;
}
bool fmissonqinghe(int apply, int posnot)
{
	if (apply == 0)
	{
		return true;
	}
	for (auto l : app[apply])
	{
		if (l==posnot)
		{
			return false;
		}
	}
	return true;
}

int main()
{
	int pointnum, fieldnum;
	cin >> pointnum >> fieldnum;
	for (int i = 1; i <= pointnum; i++)
	{
		int t;
		cin >> t;
		signnum[i] = t;
	}
	int groupnum;
	cin >> groupnum;
	for (int i = 0; i < groupnum; i++)
	{
		int fi, ai, nai, pai, paai, paari;
		cin >> fi >> ai >> nai >> pai >> paai >> paari;
		for (int j = 0; j < fi; j++)
		{
			set<int>th;
			set<int>se;
			for (int k = 1; k <= pointnum; k++)
			{
				if (signqinghe(nai, k) && missonqinghe(pai, k))
				{
					if (fmissonqinghe(paai, k))
					{
						th.insert(k);
					}
					se.insert(k);
				}
			}
			if (th.size() == 0 && paari == 0)
			{
				th = se;
			}
			if (th.size() == 0)
			{
				cout << 0 <<' ';
				continue;
			}
			else
			{
				vector<pair<int, int>>node;
				for (auto i1 : th)
					node.push_back({tasknum[i1],i1});
				sort(node.begin(), node.end());
				int result = node[0].second; 
				cout << result << " ";
				app[ai].insert(result);
				tasknum[result]++;
				
			}
		}
		cout << endl;
	}
	return 0;
}

signnum存储着不同计算区域的节点编号

app存储着不同应用的计算区域的分布情况

tasknum存储着不同计算区域的任务数量

bool signqinghe(int sign, int pos)
{
	return sign == 0 || signnum[pos] == sign;
}

对应要求1

bool missonqinghe(int apply, int pos)
{
	if (apply == 0)
	{
		return true;
	}
	int signpos = signnum[pos];
	for (auto l : app[apply])
	{
		if (signpos == signnum[l])
		{
			return true;
		}
	}
	return false;
}

对应要求2

bool fmissonqinghe(int apply, int posnot)
{
	if (apply == 0)
	{
		return true;
	}
	for (auto l : app[apply])
	{
		if (l==posnot)
		{
			return false;
		}
	}
	return true;
}

对应要求3

主函数:输入节点数和区域数,更新signnum,再输入要求数量,设置一个循环(fi表示有几个要求相同的点),设置两个哈希表分别对应符合两个要求和三个要求,遍历计算节点,更新两个哈希表的内容,然后根据题目中给定的排序操作,把符合条件的点进行排序(pair默认先排first再排second,把任务最少的计算节点挑出来作为结果,然后更新app和tasknum数组)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值