其他分享
首页 > 其他分享> > 【DFS】【剪枝】【DG特长生2011】民生问题

【DFS】【剪枝】【DG特长生2011】民生问题

作者:互联网

某市政府非常关注民生,最近对民生问题作了调研,提出了最近要解决的n个民生问题,政府的专家顾问组有w人,每一个专家都有自己的特长,政府知道每专家能解决哪些问题,现在政府想知道至少请多少位专家,才能把所有的问题都解决?


DFS+优化。
如果一个专家可以解决的任务,某一个专家全都可以解决,那么删掉前面一个专家…如果某个任务只有一个专家可以解决,那么这个专家必然被选择。瞎搞。


代码

瞎几把优化,居然加起来有50行左右…

#include<cstdio>
#include<cmath>
#include<iostream>
using namespace std;
int l[100], finish[100], n, w, ans, addd, T, ru[100], wo[100][100], L[100];
bool used[100], woo[100][100];
struct asdf{
	int to, next;
} A[500];

void dfs(int d, int ss){
	if(d == n+1){
		ans = min(ans, ss);
		return;
	}
	if(finish[d] >= 1){
		int nexx = d+1;
		while(finish[nexx] >= 1) ++nexx;
		dfs(nexx, ss);
	}
	else{
		for(int i = L[d]; i; i = A[i].next)
			if(used[A[i].to] == 0){
				used[A[i].to] = 1;
				for(int j = 1; j <= l[A[i].to]; ++j)
					++finish[wo[A[i].to][j]];
				dfs(d+1, ss+1);
				for(int j = 1; j <= l[A[i].to]; ++j)
					--finish[wo[A[i].to][j]];
				used[A[i].to] = 0;
			}
	}
}
void cl(int xx, int yy){
	if(l[xx] > l[yy]) swap(xx, yy);
	int cf = 0;
	for(int i = 1; i <= n; ++i){
		if(woo[xx][i] == 1){
			if(woo[yy][i] == 1) ++cf;
			if(woo[yy][i] != 1) break;
		}
	}
	if(cf == l[xx]){
		used[xx] = 1;
		for(int j = 1; j <= l[xx]; ++j)
			--ru[wo[xx][j]];
	}
}
void add(int aa, int bb){
	A[++T] = (asdf){bb, L[aa]}; L[aa] = T;
}
int main(){
	freopen("question.in","r",stdin);
	freopen("question.out","w",stdout);
	scanf("%d%d", &n, &w);
	ans = n;
	for(int i = 1; i <= w; ++i){
		scanf("%d", &l[i]);
		for(int j = 1; j <= l[i]; ++j){
			scanf("%d", &wo[i][j]);
			woo[i][wo[i][j]] = 1;
			++ru[wo[i][j]];
		}
		for(int j = 1; j < i; ++j){
			cl(i, j);
			if(used[i] == 1) break;
		}
	}
	for(int i = 1; i <= n; ++i)
		if(ru[i] == 1){
			for(int j = 1; j <= w; ++j)
				if(woo[j][i] == 1 && used[j] == 0){
					for(int k = 1; k <= l[j]; ++k)
						finish[wo[j][k]] = 1;
					used[j] = 1;
					++addd;
					break;
				}
		}
	for(int j = 1; j <= w; ++j)
	if(used[j] == 0){
		int kkk = 1;
		while(kkk <= l[j]){
			if(finish[wo[j][kkk]] > 0){
				wo[j][kkk] = wo[j][l[j]];
				--l[j];
			}
			else ++kkk;
		}
	}
	for(int i = 1; i <= w; ++i){
		for(int j = 1; j < i; ++j){
			cl(i, j);
			if(used[i] == 1) break;
		}
	}
	for(int i = 1; i <= n; ++i)
		if(finish[i] == 0)
		for(int j = 1; j <= w; ++j)
			if(woo[j][i] == 1 && used[j] == 0) add(i, j);
	dfs(1,0);
	printf("%d", ans + addd);
	fclose(stdin);
	fclose(stdout);
}

标签:剪枝,used,int,DG,++,DFS,wo,kkk,100
来源: https://blog.csdn.net/qq_42937087/article/details/116765387