【搜索\位集合】送给圣诞夜的贺卡

来源:互联网 发布:谷歌语音搜索软件 编辑:程序博客网 时间:2024/04/30 13:01
描述 Description  每年的12月24日,是圣诞老人忙碌的日子,也只有这一天,他才会忙碌起来。面对着将要来临的宁静的夜晚,是一种怎样的幸福和安宁感。作为圣诞老人的第一件事,就是需要为世界各地的孩子们写上贺卡,带上自己的祝福和礼品送给他们。毕竟,世界上那么多可爱的孩子,要给他们每一个人写一封贺卡,单凭自己的力量是不足以完成的。
  众所周知,一直陪伴在圣诞老人身边的是快乐的小精灵们。他们为圣诞老人而工作,其实是一个很乐意的事情。冰天雪地的北极,是他们的家,是圣诞老人的家。圣诞老人一直以来对于贺卡的书写非常重视,他也一直请一些优秀的小精灵们去帮助他完成这件事……
  12月24日早上7点钟。北极圣诞区开了一个会,会议由圣诞老人主持,在会的其他都是小精灵们,他们似乎都非常高兴,原因是等待圣诞老人的一份名单。这份名单里面的人都是这些小精灵们,一共n有个小精灵。这n个小精灵是圣诞老人根据这一年大家的表现状况(比如说谁吃饭吃得最多、谁调制的巧克力最好吃、谁的笑声最大、谁最不喜欢哭等等因素)而制定的预选的书写贺卡者名单。
  圣诞老人一个一个字,饱含激情地念出了每一个预选的小精灵。鼓掌……
  可是,接下来。并不是这个预选名单里面的所有小精灵都可以参加贺卡书写这个合作性任务。因为在以前的贺卡书写合作任务中,有一些小精灵们因为某些原因而对书写的格式和书写的字体喋喋不休。所以尽量避免这种情况发生,圣诞老人必须从预选名单中选出m(1<=m<=n)个小精灵来完成这项任务。可是……每一个小精灵的贺卡书写质量又有所不同……
  圣诞老人想了想,他觉得应该在其中选择m个小精灵,使得这m个小精灵中任意两个在曾经的贺卡书写合作任务中没有发生过矛盾冲突,并且需要这m个小精灵的书写质量的总合S最高。       输入格式 Input Format  第一行一个数n。
  第二行n个数,第i个数代表预选名单中第i号小精灵的书写质量(均为非负整数)。
  接下来有若干行,每行两个不同的非负整数x和y,表示预选名单中第x号和第y号的小精灵曾经在贺卡书写合作任务中发生过冲突。       输出格式 Output Format  第一行一个数S。       样例输入 Sample Input         样例输出 Sample Output         时间限制 Time Limitation  各个测试点1s       注释 Hint  1<=n<=50,1<=x,y<=n
友情提示:可能没有矛盾关系,使用SEEKEOF和EOF都有出错的可能,请加条件判断。



这是一个01枚举的2^n的搜索。


根据矛盾关系,我们可以把和其中一个点的冲突关系抽象为一个集合,集合中的元素是与它有冲突的点。

再用另一个集合,表示当前搜索到的位置选取了哪些点。后者与当前要判断选择与否的点它的“冲突对象“集合如果无交集,则可以选择该点。

而数据范围小于等于50,很适合使用位集合,果断摒弃O(n)的数组的方法,于是我们就用O(1)实现了有无冲突的判断。

然后我稍微考虑了一下最优性剪枝。如果现在已有的权值和加上剩下能获得的最大权值和仍然小于当前最优解,则果断放弃。

第一次交TLE80。


然后,根据以上最优性剪枝,我们可以通过排序(这是一种普遍的最优性剪枝上的优化),将大的放在前面。

另外,看了题解。。。题解里还加了一个剪枝,如果和其他点没有冲突的点必须选择。。


然后就过了。


这是一个位集合使用的好范例。

#include <cstdio>#include <string>#include <cstring>#include <algorithm>using std::sort;typedef long long ll;long ans = 0;long n;ll conflict[60];long v[60];long sum[60];long hash[60];bool wc[60];long getint(){long rs=0;bool sgn=1;char tmp;do tmp = getchar();while (!isdigit(tmp)&&tmp!='-');if (tmp=='-'){tmp=getchar();sgn=0;}do rs=(rs<<3)+(rs<<1)+tmp-'0';while (isdigit(tmp=getchar()));return sgn?rs:-rs;}void dfs(long u,ll s,long c){if (u == n + 1){if (c > ans)ans = c;return;}if (c + sum[u] <= ans)return;if (wc[u])dfs(u+1,s,c);if (!(conflict[u] & s)){dfs(u+1,s | (1ll<<(u-1)),c+v[u]);}}struct node{long v;long i;bool operator<(const node& n2)const{return v>n2.v;}};node tmp[60];int main(){freopen("christmas.in","r",stdin);freopen("christmas.out","w",stdout);n = getint();for (long i=1;i<n+1;i++){tmp[i].i = i;tmp[i].v = getint();}sort(tmp+1,tmp+1+n);for (long i=1;i<n+1;i++){hash[tmp[i].i] = i;v[i] = tmp[i].v;}for (long i=n;i>0;i--){sum[i] = sum[i+1]+v[i];}long a,b;while (scanf("%ld%ld",&a,&b)==2){a = hash[a];b = hash[b];conflict[a] |= 1ll<<(b-1);conflict[b] |= 1ll<<(a-1);wc[a] = true;wc[b] = true;}dfs(1,0,0);printf("%ld",ans);return 0;}


原创粉丝点击