2106【NOIP复赛模拟题(三)】【第1题】解题.doc

2106【NOIP复赛模拟题(三)】【第1题】解题.doc

  1. 1、本文档共4页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
2106【NOIP复赛模拟题(三)】【第1题】解题

【NOIP复赛模拟题(三)】【第1题】解题 Time Limit:1000MS? Memory Limit:65536K Total Submit:1 Accepted:1 Description 解题(solve.pas/c/cpp) 【题目描述】   SubRaY被布置了n道作业题,可是他一道也不会..但他知道有w位高手,并知道每位高手会做哪些题,请问SubRaY至少请多少位高手,才能把所有的题都做出来? Input   输入文件solve.in第一行两个整数n,w表示有n道作业题和w位高手,作业题以1..n编号.接下来w行,第i+1行第一个数li表示第i位高手会做的题目的数量,接下来li个数表示第i位高手会做哪些题目. Output   输出文件solve.out包含一个数,即SubRaY至少要请多少位高手 Sample Input 4 4 2 1 2 1 4 3 2 3 4 2 1 3 Sample Output 2 Source …. 搜索是基础算法.虽然近几年中NOIP搜索题占的比率并不大,但是在考试临近结束时,或者有题不会时,写一个简单的搜索程序往往会带来意想不到的结果.比如去年的金明的预算方案,有很多大牛虽然写了DP但是某一个小细节处理错了,0分;那些写搜索的反而至少能得40-50分,加几条剪枝甚至能达到80-90分.可见搜索在实战中的作用. 这道题并不难,只需加几条剪枝就可全过: 1 可行性剪枝,如果当前选择的高手的数量已经大于等于当前最优解的数量,剪.这也是最基础,最简单,但却是最实用的剪枝之一. 2 重复数据 数据中不可避免地会出现某一个高手会做的题目,有另外一个高手全会做的情况.这种情况下,这个高手就不需要了,因为它完全可以被另外那个高手取代. 3 仅有情况 有的题只能被一位高手解决,所以在搜索之前把这位高手会做的题目删去吧,最优解中一定包含这位高手,所以这些题一定能被解决. 对比(限时100s):裸搜(程序由@潘帕斯雄鹰大牛提供) 加一条剪枝(可行性剪枝): 加全部三条剪枝: 可见剪枝的作用是巨大的. 程序: var m,n,i,j,k,min,now:longint; a,p:array[1..100,1..100]of longint; d:array[1..100,1..100]of boolean; b,num,l:array[1..100]of longint; t:array[1..100]of boolean; bb:boolean; procedure dfs(k,now:longint); {当前第一个没被确定的} var i,j,w:longint; begin if km then begin if nowmin then min:=now; exit end; if now=min-1 then exit; for i:=1 to num[k] do begin w:=p[k,i]; for j:=1 to l[w] do inc(b[a[w,j]]); j:=k+1; while b[j]0 do inc(j); dfs(j,now+1); for j:=1 to l[w] do dec(b[a[w,j]]) end end; begin readln(m,n); for i:=1 to n do begin read(l[i]); for j:=1 to l[i] do begin read(a[i,j]); d[i,a[i,j]]:=true; end end; for i:=1 to n do {判断与别人重复的高手} for j:=1 to n do if (ij) and (not t[i]) and (not t[j]) then begin bb:=true; for k:=1 to m do if d[i,k] and not d[j,k] then begin bb:=false; break end; if bb then t[i]:=true end; for i:=1 to n do if not t[i] then begin {设置会a[i,j]的高手} for j:=1 to l[i] do begin inc(num[a[i,j]]);

文档评论(0)

shenlan118 + 关注
实名认证
内容提供者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档