B站带我打codeforces(二)

D. Dr. Evil Underscores

原题地址
在这里插入图片描述
代码:
题目大意:给n个数字,让你求一个数X,使得X和每个数的异或值的最大值最小
其实看到最大值最小这样的表述很容易向二分方向想,但显然这题没法二分,只能字典树+DP
先将每个数变成30位的二进制数,然后建立字典树,在字典树上搞树上DP
qsc讲解
在这里插入图片描述
qsc的代码省略了建树的过程(一边DP一边建)

E. Xenon’s Attack on the Gangs

原题地址
在这里插入图片描述
在这里插入图片描述
代码:
题目大意:给一棵树的每个边赋一个权值(0到n-2),定义一个路径的值为这条路径所有边中没出现的最小自然数,使得所有路径之和最少。
显然,把比较小的权全都放在一起比较好
qsc视频讲解
代码
有意的地方在于,DP的过程,当i与j不相邻时,dp[i][j]=-1,而当中间的链都推完时,则可以运行到求dp[j][i],两者等价

E. Erase Subsequences

原题地址
在这里插入图片描述在这里插入图片描述
代码:
题目大意:给一个s串和一个t串,先提取s的一个子序列组成t1串,然后在剩下的里面提取一个t2,问t1和t2能否组成t串
qsc视屏讲解
正反则逆,我们考虑将t化成两个字符串,去寻找匹配的s子序列
现将t分成两个子串,然后去匹配s;
一个神奇的DP,dp[i][j]表示s取到第i个字符,t1取到第j个字符所能匹配到的t2的最大值

//代码摘自qsc视频讲解
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<map>
#include<vector>
using namespace std;
typedef long long ll;
#define maxn 405
#define pi 3.1415926
const int mod=1e9+7;
int dp[maxn][maxn];
bool check(string s,string t)//先判断一个子串能不能解决
{
	int idx=0;
	if(!t.size()) return true;
	for(int i=0;i<s.size();i++)
	{
		if(s[i]==t[idx]) idx++;
		if(idx==t.size()) return true;
	}
	return false;
}
bool check(string s,string t1,string t2)
{
	memset(dp,-1,sizeof(dp));
	dp[0][0]=0;
	for(int i=0;i<s.size();i++)
	{
		for(int j=0;j<=t1.size();j++)
		{
			if(dp[i][j]>=0)
			{
				if(j<t1.size()&&t1[j]==s[i])//与t1匹配
				{
					dp[i+1][j+1]=dp[i][j];
				}
				if(dp[i][j]<t2.size()&&t2[dp[i][j]]==s[i])//与t2匹配
				{
					dp[i+1][j]=max(dp[i+1][j],dp[i][j]+1);
				}
				dp[i+1][j]=max(dp[i+1][j],dp[i][j]);
			}
		}
	}
	int res1=dp[s.size()][t1.size()];//最大匹配
	int res2=t2.size();
	if(res1>=res2) return true;
	else return false;
}
void solve()
{
	string s,t;
	cin>>s>>t;
	if(check(s,t))
	{
		cout<<"YES"<<endl;
		return;
	}
	for(int i=0;i<t.size()-1;i++)//枚举切割位置
	{
		string t1="",t2="";
		for(int j=0;j<=i;j++) t1+=t[j];
		for(int j=i+1;j<t.size();j++) t2+=t[j];
		bool res=check(s,t1,t2);
		if(res)
		{
			cout<<"YES"<<endl;
			return;
		}
	}
	cout<<"NO"<<endl;
	return;
}
int main()
{    
	ios::sync_with_stdio(false);
	int t;
	cin>>t;
	while(t--)
	{
		solve();
	}
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值