G. Rudolf and CodeVid-23 codeforces1846G

11 篇文章 0 订阅
10 篇文章 0 订阅

Problem - G - Codeforces

题目大意:给出一长度为n的二进制字符串s,和m对二进制字符串e1和e2,,费用为d,s和一对字符串操作后s中是1且e1中也是1的位置会变成0,s中是0,e2中是1的位置会变成1,得到新的s,每对字符串可以操作任意次,问能否使s变成全0字符串

1<=n<=10;1<=m<=1000;1<=d<=1000

思路:可以发现s和一对字符串操作,就相当于s&(~e1)|e2(可以用真值表推导),因为字符串的位数最高是10位,也就是说无论怎么操作,最多出现1024个不同的字符串,所以我们可以把每个不同的字符串当做一个节点,先用bitset把字符串都转化为数字,然后每一对字符串作为边,用set来做bfs的队列,从起点开始,将set中的每个点都用上面的到的公式与每对字符串进行操作,如果到新的的距离小于之前记录的距离,就更新这个最短距离,最后队列为空后输出到0点的距离即可

//#include<__msvc_all_public_headers.hpp>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e3 + 5;
ll n, m;
pair<ll, pair<ll, ll>>e[N];
ll dis[5000];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin >> t;
	while (t--)
	{
		cin >> n >> m;
		bitset<10>sx;
		cin >> sx;
		ll s = sx.to_ullong();//将二进制字符串转化为long long型数据
		for (int i = 1; i <= m; i++)
		{
			ll dx;
			bitset<10>ux, vx;
			cin >> dx >> ux >> vx;
			ll u = ux.to_ullong();
			ll v = vx.to_ullong();
			e[i].first = dx;
			e[i].second = make_pair(u, v);//记录每对字符串的费用,和e1,e2对应的数字
		}
		for (int i = 0; i <= (1 << (n + 1)); i++)
		{//初始化每个点到起点的距离
			dis[i] = 0x7fffffff;
		}
		dis[s] = 0;
		set<pair<ll, ll>>q = { make_pair(0, s) };//用集合记录创造出的点,及到其的最短距离,避免重复
		while (!q.empty())
		{
			pair <ll, ll> temp = *q.begin();
			q.erase(q.begin());//set弹出堆顶元素的方法
			ll d = temp.first;
			ll u = temp.second;
			for (int i = 1; i <= m; i++)
			{
				ll v = u & (~e[i].second.first) | e[i].second.second;//得到新的点
				if (dis[v] > d + e[i].first)
				{
					q.erase(make_pair(dis[v], v));//更新距离要把原先记录的删掉
					dis[v] = d + e[i].first;
					q.insert(make_pair(dis[v], v));
				}
			}
		}
		if (dis[0] == 0x7fffffff)
		{//到终点的距离没更新,就是没通路
			cout << -1 << endl;
		}
		else
		{
			cout <<dis[0] << endl;
		}
	}
	return 0;
}

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

timidcatt

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值