ARC083简要题解

开幕雷击系列。
在这里插入图片描述
最后一题真的神仙,不会。

C题:
发觉这东西好像可以背包。
然后背出来枚举一枚举就行。
貌似直接枚举也行?
注意判答案是时候有个式子 S u g a r 1 T o t 1 < S u g a r 2 T o t 2 \frac{Sugar_1}{Tot_1}<\frac{Sugar_2}{Tot_2} Tot1Sugar1<Tot2Sugar2满足这条件的时候应该替换答案。
如果初始值并没有设置成 T o t = a , S u g a r = 0 Tot=a,Sugar =0 Tot=a,Sugar=0,那么上面那个式子需要加等号。不然万一给出巧妙的数据,让你最后得到一杯无糖水,不加等号就会挂。
本来准备实况的,然后开幕雷击之后就光速掐掉了HHHHHHHH

#include <bits/stdc++.h>
using namespace std;
int n, m;
bool wat[6010];
bool sug[6010];
int A, B, C, D, E, F;
int main() { 
	scanf("%d%d%d%d%d%d", &A, &B, &C, &D, &E, &F);
	wat[0] = 1;
	for(int i=0;i<=3000;++i) 
		wat[i+A] |= wat[i];
	for(int i=0;i<=3000;++i)
		wat[i+B] |= wat[i];
	sug[0] = 1;
	for(int i=0;i<=3000;++i) 
		sug[i+C] |= sug[i];
	for(int i=0;i<=3000;++i)
		sug[i+D] |= sug[i];
	long long watsug = 100, nsug = 0;
	for(int i=1;i*100<=F;++i) { 
		if(wat[i]) { 
			for(int j=0;j<=3000;++j) { 
				if(!sug[j]) 
					continue;
				if(E * i >= j) { 
					if(i * 100 + j > F)
						continue;
					long long nwtot = i * 100 + j;
					long long nwsug = j;
					if(nwsug * watsug >= nwtot * nsug) //就是这里的等号
						watsug = nwtot, nsug = nwsug;
				} 
			} 
		} 
	} 
	printf("%lld %lld\n", watsug, nsug);
	return 0;
}
//没加那个等号的话,5 6 7 8 100 500就能卡。

D题:
这题有点意思,适合拿来签到。
一个小性质:最短路一定是某两条最短路拼起来。
所以 O ( n 3 ) O(n^3) O(n3)枚举边和中间点,如果他能被拼起来恰好等于,那么这条新的边废了。
如果他比拼起来的还要长,那么这图挂了。

#include <bits/stdc++.h>
using namespace std;
int n;
int mp[510][510];
int res[510][510];
int main() { 
	scanf("%d", &n);
	for(int i=1;i<=n;++i) { 
		for(int j=1;j<=n;++j) { 
			scanf("%d", &mp[i][j]);
		} 
	} 
	bool valid = 1;
	for(int l=1;l<=n;++l) { 
		for(int r=1;r<=n;++r) { 
			bool ok = 0;
			for(int mid=1;mid<=n;++mid) { 
				if(mid == l || mid == r) 
					continue;
				if(mp[l][r] == mp[l][mid] + mp[mid][r]) { 
					ok = 1;
				} 
				if(mp[l][r] > mp[l][mid] + mp[mid][r]) { 
					valid = 0;
				} 
			} 
			if(!ok) { 
				res[l][r] = mp[l][r];
			} 
		} 
	} 
	long long ans = 0;
	for(int i=1;i<=n;++i) 
		for(int j=1;j<=n;++j) 
			ans += res[i][j];
	if(!valid) 
		ans = -2;
	cout<<ans/2;
	return 0;
} 

//5 6 1 1 100 500

E题:
分析一下发觉,我们在保证同色的前提下,让异色尽量小就完事了。
证明在注释里(
然后发觉颜色并不重要,因为我们可以随时inverse一个子树。
然后发现他就是个长得很像背包的东西了,树上DP一下,转一转。
感觉这题可以魔改一下www
注释还是赛时思考的时候写的

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

vector<int>ed[1010];
int dp[2010];
int pac[5010][6010];
int lim[3010];
const int ma = 0x3f3f3f3f;
bool possible = 1;
int pcnt, n;

inline void ade(int l, int r) { 
	ed[l].push_back(r);
	ed[r].push_back(l);
} 

void solve(int nw, int fro) { 
	if(!possible)
		return;
	for(int i=0;i<ed[nw].size();++i) {
		if(!possible)
			return;
		int tar = ed[nw][i];
		if(tar == fro) 
			continue;
		solve(tar, nw);
	}
	if(!possible)
		return;
	++pcnt;
	pac[pcnt][0] = 0;
	for(int i=0;i<ed[nw].size();++i) { 
		int tar = ed[nw][i];
		if(tar == fro)
			continue;
		int val1 = dp[tar], val2 = lim[tar];
		for(int j = 0; val1 + j <= 5000; ++j) 
			pac[pcnt + 1][val1 + j] = min(pac[pcnt + 1][val1 + j], pac[pcnt][j] + val2);
		for(int j = 0; val2 + j <= 5000; ++j)
			pac[pcnt + 1][val2 + j] = min(pac[pcnt + 1][val2 + j], pac[pcnt][j] + val1);
		++pcnt;
	} 
	int ano = ma;
	for(int i=0;i<=lim[nw];++i) 
		ano = min(ano, pac[pcnt][i]);
	if(ano == ma) { 
		possible = 0;
		return;
	} 
	else 
		dp[nw] = ano;
	return;
} 

int main() { 
	memset(pac, 0x3f, sizeof(pac));
	scanf("%d", &n);
	int fa;
	for(int i=2;i<=n;++i) 
		scanf("%d", &fa), ade(i, fa);
	for(int i=1;i<=n;++i) 
		scanf("%d", &lim[i]);
	solve(1, 1);
	printf(possible ? "POSSIBLE" : "IMPOSSIBLE");
	return 0;
} 

/*
 * 重量轻的情况一定优于重量重的情况
 * 吗?
 * mdzz这不废话,如果他瘦了,你在根让他胖回来就完事。
 * 然后那个分配重量就变成了最小化一个重量。
 * emm好像并不太需要关心这个子树里面究竟是什么颜色。
 * 假设他的根为某种颜色,我们直接对该子树进行颜色reverse,一样是不发生变化的
 * 那么,DP[i]表示,当前做了i号点的限制,i子树里面,另一个颜色的最小sum是DP[j]
 * 怎么感觉是个背包变形啊。
 * 对,貌似还真是个背包变形。
 * 考虑转移,在i的时候,开个pac[i][5010],初始让pac[i][0] = 0, 其他都是inf
 * 枚举所有的儿子,每次俩转移:转或不转。
 * 注意不能继承上一次的状态,一定得新转,继承会挂。
 * 好麻烦.jpg
 * emm我还得滚一下咯?
 * 诶不对。我开个cnt就完事好像。
 * 
*/

F:
神仙,不会,GG,跑路
能想到建图,然后顺序那块完全处理不动。
先来说说我想到的吧。
稽器人机器人当成点,球当成边。
则,一个球只可能被两个机器人中的一个拿走,一个边两个点,非常科学。
建个图,变成给每个点找个边与它对应,要求不重不漏,图保证点数=边数。
显然只有基环树/基环树森林有解。
然后就不会了qwq。顺序那里想不动。

跑路之后膜了波题解爸爸,还是没看太懂。
被拓扑序那块搞懵逼了。
就先坑在这里吧。
Orz题解爸爸
https://www.luogu.com.cn/problem/solution/AT3537

另外吐槽一句luogu的题目难度评级
这题和E题居然都是紫题
怎么感觉他俩显然不是一个难度等级的
果然大家都是在用脚投票吗
另外就是,在找题解的时候,我看到了这么一句话。
在这里插入图片描述
BKSN Atcoder!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值