BZOJ4057: [Cerc2012]Kingdoms

BZOJ4057: [Cerc2012]Kingdoms

https://lydsy.com/JudgeOnline/problem.php?id=4057

分析:

  • 沙茶状压
  • 预处理出来(num_{i,j})表示(j)状态下(i)是否可能破产。
  • 然后转移即可。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
#define N 22
#define M (1<<20)
int n,d[N][N];
int num[N][M],p[M];
bool f[M];
int main() {
	int T;
	scanf("%d",&T);
	while(T--) {
		scanf("%d",&n);
		int i,j;
		for(i=0;i<n;i++) p[1<<i]=i+1;
		for(i=1;i<=n;i++) for(j=1;j<=n;j++) scanf("%d",&d[i][j]);
		int mask=(1<<n)-1;
		for(i=0;i<=mask;i++) f[i]=0;
		f[mask]=1;
		for(i=1;i<=n;i++) {
			for(j=1;j<=mask;j++) {
				int k=j&(-j);
				num[i][j]=num[i][j-k]+d[i][p[k]];
			}
		}
		for(i=mask;i;i--) if(f[i]) {
			for(j=1;j<=n;j++) if(i&(1<<(j-1))) {
				if(num[j][i]>0) {
					f[i-(1<<(j-1))]=1;
				}
			}
		}
		int flg=0;
		for(i=1;i<=n;i++) if(f[1<<(i-1)]) {
			if(flg) printf(" %d",i);
			else flg=printf("%d",i);
		}
		if(!flg) printf("0");
		puts("");
	}	
}

原文地址:https://www.cnblogs.com/suika/p/10204674.html