AOJ.863 分书问题 (DFS)

题意分析

现有n个人,n种书,给出每人对n种书的喜欢列表,求有多少种方案满足以下条件:

1.每个人都分得自己喜欢的书;
2.每个人分得书的种类各不相同,即所有种类的书均得到分配

1.采用生成测试法
生成过程
对于每个人来说,枚举每本书的状态(0/1),有2^20;
最多有20个人 ,则有20*2^20 = 10*2^21 ≈ 10^3 * 10 ^3 * 10 = 10^ 7
考虑上测试的时间,TLE。

2.优化
充分利用题目中给的信息,即每个人对不同书的喜爱我们是已知的。对于每个人来说,我们不需要枚举全部书籍的状态,只需要枚举他喜爱的每本书的状态,即从他喜欢的书籍中选一本给他,然后再看下一个人,再从这个人喜爱的书籍中选一本给他…… 直到所有人都分得书籍。然后再检查是否所有的书籍都得到分配,若是,ans++,否则继续枚举下一种分配情况。

代码总览

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <sstream>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <cmath>
#define INF 0x3f3f3f3f
#define nmax 25
#define MEM(x) memset(x,0,sizeof(x))
using namespace std;
vector<int> v[nmax];
bool bookvisit[nmax];
bool peoplevisit[nmax];
int ans = 0,n;
bool check()
{
    for(int i = 0; i<n;++i){
        if(!bookvisit[i] || !peoplevisit[i])
            return false;
    }
    return true;
}
void dfs(int peo)
{
    if(peo == n){
        if(check()) ans++;
        return;
    }
    peoplevisit[peo] = true;
    for(int i = 0; i<v[peo].size();++i){
        if(!bookvisit[v[peo][i]]){
            bookvisit[v[peo][i]] = true;
            dfs(peo+1);
            bookvisit[v[peo][i]] = false;
        }
    }
}
void init()
{
    MEM(peoplevisit);
    MEM(bookvisit);
    ans = 0;
}
int main()
{
    //freopen("in.txt","r",stdin);
    char str[nmax];
    while(scanf("%d",&n)!= EOF){
        init();
        for(int i =0 ;i<n; ++i){
            scanf("%s",str);
            for(int j = 0;j< strlen(str);++j)
                if(str[j] == '1') v[i].push_back(j);
        }
        dfs(0);
        printf("%d\n",ans);
    }
    return 0;
}
posted @ 2017-04-28 21:11  pengwill  阅读(151)  评论(0编辑  收藏  举报