【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