[luoguP2622] 关灯问题II(状压最短路)

传送门

本以为是状压DP,但是有后效性。

所以写一手状压spfa

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#define N 11
#define M 101

int n, m;
int a[M][N], dis[1 << N];
std::queue <int> q;
bool vis[1 << N];

inline int read()
{
	int x = 0, f = 1;
	char ch = getchar();
	for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
	for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
	return x * f;
}

inline void spfa()
{
	int i, j, u, v;
	memset(dis, 127 / 3, sizeof(dis));
	dis[0] = 0;
	q.push(0);
	while(!q.empty())
	{
		u = q.front();
		vis[u] = 0;
		q.pop();
		for(i = 1; i <= m; i++)
		{
			v = u;
			for(j = 1; j <= n; j++)
			{
				if(a[i][j] == 1 && !(v & (1 << j - 1))) v |= 1 << j - 1;
				if(a[i][j] == -1 && (v & (1 << j - 1))) v ^= 1 << j - 1;
			}
			if(dis[v] > dis[u] + 1)
			{
				dis[v] = dis[u] + 1;
				if(!vis[v])
				{
					q.push(v);
					vis[v] = 1;
				}
			}
		}	
	}
}

int main()
{
	int i, j;
	n = read();
	m = read();
	for(i = 1; i <= m; i++)
		for(j = 1; j <= n; j++)
			a[i][j] = read();
	spfa();
	printf("%d
", dis[(1 << n) - 1] <= 1e8 ? dis[(1 << n) - 1] : -1);
	return 0;
}

  

原文地址:https://www.cnblogs.com/zhenghaotian/p/7352311.html