NOIp模拟 解题
来源:互联网 发布:批量重命名软件 编辑:程序博客网 时间:2024/06/06 23:58
〖题目描述〗SubRaY 被布置了n 道作业题,可是他一道也不会..但他知道有w 位
高手,并知道每位高手会做哪些题,请问SubRaY 至少请多少位高手,才能把所有
的题都做出来?
〖输入〗[solve.in]第一行两个整数n,w 表示有n 道作业题和w 位高手,作业题
以1..n 编号.接下来w 行,第i+1 行第一个数li 表示第i 位高手会做的题目的数
量,接下来li 个数表示第i 位高手会做哪些题目.
〖输出〗[solve.out]一个数,SubRaY 至少要请多少位高手.
〖样例输入〗
4 4
2 1 2
1 4
3 2 3 4
2 1 3
〖样例输出〗
2
〖数据范围〗
对于40%的数据,3<=n,w<=10,
对于100%的数据,3<=n,w<=60,1<=li<=6
高手,并知道每位高手会做哪些题,请问SubRaY 至少请多少位高手,才能把所有
的题都做出来?
〖输入〗[solve.in]第一行两个整数n,w 表示有n 道作业题和w 位高手,作业题
以1..n 编号.接下来w 行,第i+1 行第一个数li 表示第i 位高手会做的题目的数
量,接下来li 个数表示第i 位高手会做哪些题目.
〖输出〗[solve.out]一个数,SubRaY 至少要请多少位高手.
〖样例输入〗
4 4
2 1 2
1 4
3 2 3 4
2 1 3
〖样例输出〗
2
〖数据范围〗
对于40%的数据,3<=n,w<=10,
对于100%的数据,3<=n,w<=60,1<=li<=6
这题搜索做的话,比较暴力,但可以优化
1、对于当前搜索层数与解比较,若比已得出解大,退出。(谁不会啊)
2、你是大犇,我是菜比,你会12345题我会135题,这时只要大牛,不要菜比。
3、发现一个题目会的人越少成为解的可能性越大,这是就要越优先选择他。(强剪)
#include<cmath>#include<cstdio>#include<vector>#include<string>#include<cstring>#include<iostream>#include<algorithm>#define N 66using namespace std;const int inf=1<<30;int n,w,vis[N],useful[N],prob[N],can[N][N],done[N];vector <int>master[N];int ans=inf;int flag=0;bool useful_judge(int k){ int p[N],cnt; memset(p,0,sizeof p); for (int i=0;i<master[k].size();i++) p[master[k][i]]=1; for (int i=1;i<=w;i++) if (i!=k) { cnt=0; for (int j=0;j<master[i].size();j++) if (p[master[i][j]]) cnt++; if (cnt==master[k].size() && master[k].size()<master[i].size()) return 0; } return 1;}void init(){ memset(vis,0,sizeof vis); memset(hashv,0,sizeof hashv); memset(can,0,sizeof can); memset(done,0,sizeof done); cin >> n >>w; int tmp,li; for (int i=1;i<=w;i++) { scanf("%d",&li); for (int j=1;j<=li;j++) { scanf("%d",&tmp); master[i].push_back(tmp); prob[tmp]++; can[i][tmp]=1; } } for (int i=1;i<=w;i++) useful[i]=useful_judge(i);}void dfs(int k,int sum){ if (!sum) {ans=min(ans,k);return;} if (k>=ans||k==n) return; int id,minv=inf; for (int i=1;i<=n;i++) if (prob[i]<minv && !done[i]) id=i,minv=prob[i]; int tmp[N],p; for (int i=1;i<=w;i++) if (!vis[i] && useful[i] && can[i][id]) { vis[i]=1;p=0; for (int j=0;j<master[i].size();j++) if (!done[master[i][j]]) { tmp[++p]=master[i][j]; done[master[i][j]]=1; } dfs(k+1,sum-p); vis[i]=0; for (int j=1;j<=p;j++) done[tmp[j]]=0; }}int main(){ freopen("solve.in","r",stdin); freopen("solve.out","w",stdout); init(); dfs(0,n); cout << ans <<endl; return 0;}
0 0
- NOIp模拟 解题
- 10.24南海NOIP模拟测解题报告
- 07年NOIp模拟赛by Matrix67 解题报告
- 【WZOI第二次NOIP模拟赛Day1T1】神秘大门 解题报告
- 【WZOI第二次NOIP模拟赛Day1T2】世界末日 解题报告
- 2014NOIP复赛模拟练习 设置喷水池 解题报告
- NOIP模拟题 kun 栈 贪心 解题报告
- codevs 1164 || NOIP 2007 统计数字 模拟 解题报告
- Noip模拟
- 【NOIP模拟】20151004模拟
- 【NOIP模拟】 20151005模拟
- 【NOIP模拟】 20151006模拟
- 【NOIP模拟】 20151007模拟
- 【NOIP模拟】20151014模拟
- 【NOIP模拟】20151015模拟
- [NOIP 2012]解题报告
- NOIP 解题有感
- NOIP解题报告
- 几种弹出对话框方式
- Fragment
- Hadoop伪分布式集群搭建
- Java---关于forward和redirect的描述
- 浅谈L0,L1,L2范数及其应用
- NOIp模拟 解题
- ubuntu安装IDEA2016
- 161113
- C#——构造函数
- ubuntu下opencv安装
- c#使用aspose.cells 从datatable导出数据到excel
- 9C切面条
- C++模板与泛型编程
- Android动态加载入坑指南