软件补丁问题(状态压缩 最短路)

先状态压缩,再求费用流,但耗内存太大,改变存边方式降低内存使用。

直接求最短路即可

//http://www.cnblogs.com/IMGavin/
#include <iostream>
#include <stdio.h>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <vector>
#include <map>
#include <stack>
#include <set>
#include <bitset>
#include <algorithm>
using namespace std;

typedef long long LL;
#define gets(A) fgets(A, 1e8, stdin)
const int INF = 0x3F3F3F3F, N = 2000008, M = 108;
int n, m;
int b1[M], b2[M], f1[M], f2[M], cost[M];

const double EPS = 1e-6;
int dis[N];
bool inq[N];

char str[1000];

int SPFA(int st, int des){
	memset(inq, 0, sizeof(inq));
	memset(dis, 0x3f, sizeof(dis));
	queue <int> q;
	q.push(st);
	dis[st] = 0;
	inq[st] = true;
	while(!q.empty()){
		int u = q.front();
		q.pop();
		inq[u] = false;
		for(int i = 0; i < m; i++){
			if(( (u & b1[i]) == b1[i]) && ( (u & b2[i]) == 0)){
				int v = u & (~f1[i]) | f2[i];
				if(dis[v] > dis[u] + cost[i]){
					dis[v] = dis[u] + cost[i];
					if(!inq[v]){
						inq[v] = true;
						q.push(v);
					}
				}

			}
		}
	}
	if(dis[des] >= INF){
			return 0;
	}
	return dis[des];
}


int main(){
	while(cin >> n >> m){
		memset(b1, 0, sizeof(b1));
		memset(b2, 0, sizeof(b2));
		memset(f1, 0, sizeof(f1));
		memset(f2, 0, sizeof(f2));

		int st = (1<<n) - 1, des = 0;
		for(int k = 0; k < m; k++){
			scanf("%d", &cost[k]);
			scanf("%s", str);
			for(int i = 0; i < n; i++){
				if(str[i] == '+'){
					b1[k] |= (1 << i);
				}else if(str[i] == '-'){
					b2[k] |= (1 << i);
				}
			}

			scanf("%s", str);
			for(int i = 0; i < n; i++){
				if(str[i] == '-'){
					f1[k] |= (1 << i);
				}else if(str[i] == '+'){
					f2[k] |= (1 << i);
				}
			}
		}
		printf("%d
", SPFA(st, des));
	}

	return 0;
}

  

原文地址:https://www.cnblogs.com/IMGavin/p/6391296.html