2022LDU寒假训练-程序补丁

3 篇文章 0 订阅
1 篇文章 0 订阅
本文介绍了一种程序补丁应用的问题,其中每个补丁都有特定的使用条件和副作用。目标是找到修复所有错误的最小总耗时。通过状态压缩和SPFA(Shortest Path Faster Algorithm)算法来解决这个问题。程序初始状态为多个错误,补丁可以修正错误,但可能引入新的错误。最终,通过位运算和状态转移找到最优解。
摘要由CSDN通过智能技术生成

程序补丁

问题描述

一个程序总有个错误,公司经常发布补丁来修正这些错误,遗憾的是,每用一个补丁,在修正某些错误的时候,同时会加入某些错误,每个补丁都有一定运行时间。
某公司发表了一个游戏,出现了n个错误B={b1,b2,b3,…,bn},于是该公司发布了m个补丁,每个补丁的应用都是有条件的(即哪些错误必须存在,哪些错误不能存在)。
求最少需要多少时间可全部修正这些错误。

输入

输入文件第一行有两个正整数n和m,n表示错误总数,m表示补丁总数,1≤n≤20, 1≤m≤100。接下来m行给出了m个补丁的信息。每行包括一个正整数(表示此补丁程序的运行时间)和两个字符串,
第一个字符串描述了应用该补丁的条件。字符串的第i个字符,如果是‘+’,表示在软件中必须存在第bi号错误;如果是‘-’,表示软件中错误bi不能存在;如果是‘0’,则表示错误bi存在或不存在均可(即对应用该补丁没用影响)。
第二个字符串描述了应用该补丁的效果。字符串的第i个,如果是‘+’,表示产生了一个新错误bi;如果是‘-’,表示错误bi被修改好了;如果是‘0’,则表示错误bi不变(即原来存在的,仍然存在;原来不存在,还是不存在)。

输出

输出一个整数,如果问题有解,输出总耗时。否则输出-1。

Sample Input

3 5
1 0-+ -+-
3 +-- -00
4 000 00-
6 +0+ -0-
3 0+0 0-0

Sample Output

7

题目大意

最开始有很多bug,我们把bug标记成+
所以最开始是+++,我们的目标是—
每一个补丁必须满足条件才可以使用,但是该补丁也会造成新bug。那么你的任务是找到一个最优方案去修补所有的bug。

思路解析

这题主要是两个知识点,一个是状态压缩,另一个则是spfa算法的使用。
这里spfa也可以用Dijkstra堆优化的方法去完成构造。
因为这里的图是每一个点之间可能能够构成,也可能不能构成入度。
所以我门对于每一个出度都要暴力跑一遍所有的节点,看看能否联通然后用spfa直接跑
状态压缩就是每一个字符的节点无非就是0 or 1.我们可以开int 能够存储 32个保证够用。
接下来就是位运算的操作了。
这里需要注意,他的位置一共有220可能性

Accepted Code

//#include<unordered_map>
#include<algorithm>
#include<iostream>
#include<string.h>
#include <iomanip>
#include<stdio.h>
#include<vector>
#include<string>
#include<math.h>
#include<cmath>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll ll_inf = 9223372036854775807;
const int int_inf = 2147483647;
const short short_inf = 32767;
const ll less_inf = 0x3f3f3f3f;
const char char_inf = 127;
#pragma GCC optimize(2)
#define accelerate cin.tie(NULL);cout.tie(NULL);ios::sync_with_stdio(false);
#define PI 3.141592653589793
#define EPS 1.0e-8
ll gcd(ll a, ll b) {
	return b ? gcd(b, a % b) : a;
}
ll lcm(ll a, ll b) {
	return a / gcd(a, b) * b;
}
inline ll read() {
	ll c = getchar(), Nig = 1, x = 0;
	while (!isdigit(c) && c != '-')c = getchar();
	if (c == '-')Nig = -1, c = getchar();
	while (isdigit(c))x = ((x << 1) + (x << 3)) + (c ^ '0'), c = getchar();
	return Nig * x;
}
inline void out(ll a) {
	if (a < 0)putchar('-'), a = -a;
	if (a > 9)out(a / 10);
	putchar(a % 10 + '0');
}
ll qpow(ll x, ll n, ll mod) {
	ll res = 1;
	while (n > 0) {
		if (n & 1)res = (res * x) % mod;
		x = (x * x) % mod;
		n >>= 1;
	}
	return res;
}
#define read read()
const int MAXN = 4000000, N = 105;
int n, m;
bool judge[MAXN];
int dis[MAXN];
int A[N], B[N], C[N], D[N], val[N];
queue<int>q;
void spfa(ll sta) {
	memset(dis, 0x3f3f3f3f, sizeof(dis));
	dis[sta] = 0;
	q.push(sta);
	while (q.size()) {
		int x = q.front(), y;
		q.pop();
		judge[x] = false;
		for (int i = 0; i < m; i++) {
			if ((A[i] & x) == A[i] && (B[i] & x) == 0) {
				y = ((x | C[i]) ^ C[i]) | D[i];
				if (dis[x] + val[i] < dis[y]) {
					dis[y] = dis[x] + val[i];
					if (!judge[y])judge[y] = true, q.push(y);
				}
			}
		}
	}
}
int main()
{
	n = read, m = read;
	char a[50], b[50];
	for (int i = 0; i < m; i++) {
		scanf("%d%s%s", &val[i], a, b);
		A[i] = B[i] = C[i] = D[i] = 0;
		for (int j = 0; j < n; j++) {
			if (a[j] == '+')A[i] |= (1 << j);
			else if (a[j] == '-')B[i] |= (1 << j);
			if (b[j] == '-')C[i] |= (1 << j);
			else if (b[j] == '+')D[i] |= (1 << j);
		}
	}
	spfa((1 << n) - 1);
	out(dis[0] == 0x3f3f3f3f ? -1 : dis[0]);
	puts("");
	return 0;
}

By-Round Moon

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

落雪幻念

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

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

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

打赏作者

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

抵扣说明:

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

余额充值