zoukankan      html  css  js  c++  java
  • FZU 2165 v11(最小重复覆盖)+ codeforces 417D Cunning Gena

    告诉你若干个(<=100)武器的花费以及武器能消灭的怪物编号,问消灭所有怪物(<=100)的最小花费。。。当然每个武器可以无限次使用,不然这题就太水了╮(╯▽╰)╭

    这题当时比赛的时候连题都还没看就结束了。。。。赛后一看,果断是重复覆盖。。。

    不过之后一直没敲。。。然后今天算是补回来吧,同时也把好久以前学的DLX复习一下。。。

    DLX的话,双向十字链表。。。具体的话,百度Google什么的dancing links。。。

    一开始敲的时候还是挺顺利的,因为之前做过几次重复覆盖都是直接拿精确覆盖的模板来改。。。差不多的,不过重复覆盖就删列,代码好像还少几行呢。。。不过有时调一会有时wa上一两发。。。又鉴于最近好像好多重复覆盖的题。。。就好像spfa一样频繁出现=。=个人感觉不科学。。。

    而且之前那个精确覆盖的模板实在是无法直视,太挫了写得╮(╯▽╰)╭

    重点来了~~~代码写好了,可是不AC╮(╯▽╰)╭太可恶了。。。。让JM帮忙看代码。。。于是苦逼地一直找bug。。。。

    经过一小时吧大概的奋斗。。。JM发现。。。一个非常好笑的呵呵的亮点。。。。memset(vis,false,sizeof(false));。。。笑死我了。。。还好这是平时随便敲。。。

    然后就AC了~~~

    复杂度。。不知道怎么算DLX的复杂度哎~~~求高手教,或者说一般N,M多少可以~~

    总结就是,打代码要仔细。。。。总之不要犯这种逗比错误。。。。真正比赛的时候就笑不出来了~~~啦啦啦~~~谢谢JM~~~

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <algorithm>
      5 #include <cmath>
      6 #include <string>
      7 #include <vector>
      8 #include <queue>
      9 #include <set>
     10 using namespace std;
     11 
     12 #define ll long long
     13 #define eps 1e-8
     14 #define mod 21092013
     15 
     16 #define inf 0x3f3f3f3f
     17 #define maxr 110
     18 #define maxn (maxr*maxr)
     19 int n,m;
     20 int L[maxn],R[maxn],U[maxn],D[maxn],cnt;
     21 int row[maxn],col[maxn];
     22 int N[maxr],use[maxr],head[maxr];
     23 void init(){
     24     memset(head,-1,sizeof(head));
     25     memset(N,0,sizeof(N));
     26     for(int i=0;i<=m;++i){
     27         L[i]=i-1,R[i]=i+1;
     28         U[i]=D[i]=i;
     29         row[i]=0,col[i]=i;
     30     }
     31     L[0]=m,R[m]=0;
     32     cnt=m;
     33 }
     34 void remove(int x){// 删除列
     35     for(int i=D[x];i!=x;i=D[i])
     36         L[R[i]]=L[i],R[L[i]]=R[i];
     37 }
     38 void resume(int x){// 恢复列
     39     for(int i=D[x];i!=x;i=D[i])
     40         L[R[i]]=R[L[i]]=i;
     41 }
     42 int low(){
     43     int mi=maxr,idx=0;
     44     for(int i=R[0];i;i=R[i])if(N[i]<mi)mi=N[i],idx=i;
     45     return idx;
     46 }
     47 void link(int r,int c){
     48     ++N[c],++cnt;
     49     row[cnt]=r,col[cnt]=c;
     50     U[cnt]=U[c],D[cnt]=c;
     51     U[D[cnt]]=D[U[cnt]]=cnt;
     52     if(head[r]==-1)
     53         head[r]=L[cnt]=R[cnt]=cnt;
     54     else {
     55         L[cnt]=L[head[r]];
     56         R[cnt]=head[r];
     57         L[R[cnt]]=R[L[cnt]]=cnt;
     58     }
     59 }
     60 int cost[maxr];
     61 int ans;
     62 void dance(int dep,int val){
     63     if(R[0]==0){
     64         ans = min(ans,val);
     65         return ;
     66     }
     67     int c=low();
     68     if(c==0||val>=ans)return ;
     69     for(int i=D[c];i!=c;i=D[i]){
     70         use[dep]=i;
     71         remove(i);
     72         for(int j=R[i];j!=i;j=R[j])remove(j);
     73         dance(dep+1,val+cost[row[i]]);
     74         for(int j=L[i];j!=i;j=L[j])resume(j);
     75         resume(i);
     76     }
     77 }
     78 
     79 int main(){
     80     while(~scanf("%d%d",&m,&n)){
     81         init();
     82         bool vis[maxr];
     83         memset(vis,false,sizeof(vis));
     84         ans=0;
     85         for(int i=1;i<=n;++i){
     86             int tmp,tmp2;
     87             scanf("%d%d",cost+i,&tmp);
     88             ans+=cost[i];
     89             for(int j=0;j<tmp;++j){
     90                 scanf("%d",&tmp2);
     91                 vis[tmp2]=true;
     92                 link(i,tmp2);
     93             }
     94         }
     95         for(int i=1;i<=m;++i)if(vis[i]==false){vis[1]=false;break;}
     96         if(vis[1]==false){puts("-1");continue;}
     97         dance(0,0);
     98         printf("%d
    ",ans);
     99     }
    100     return 0;
    101 }
    View Code

    Note: 之后想起在cf上有一题类似的,当时用DLX重复覆盖超时了,要DP,然后再去试一下。。。

    结果发现有一些数据会卡掉这份代码

    在这里征求高手解答。。。。这种数据要怎么过。。。

    我的想法是预处理weapon[i]能否完全代替weapon[j]或weapon[j]+weapon[k]...不过万一他要weapon[i]+weapon[j]才能完全代替weapon[k]+weapon[l]呢...好乱...

    求高手解答....

    1 void data(){
    2     freopen("in.txt","w",stdout);
    3     puts("33 99");
    4     for(int i=0;i<99;++i)
    5         if(i<33)printf("%d %d %d
    ",998,1,i%33+1);
    6         else if(i<66)printf("%d %d %d %d
    ",998,2,i%33+1,(i+1)%33+1);
    7         else printf("%d %d %d %d %d
    ",998,3,i%33+1,(i+1)%33+1,(i+2)%33+1);
    8 }
    View Code

    参考了网上http://blog.sina.com.cn/s/blog_51cea4040100gwpv.html的剪枝优化。。。果然可以了。。。。可以跑出以上这种data了。。而且在fzu上的时间也从400+ms变成200+ms..排到第一了...有收获的感觉就是不错..这个剪枝感觉不错,好感动。。。泪牛满面,就是,当前价值+下界(不是下确界)>=best。。thank JM...

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <algorithm>
      5 #include <cmath>
      6 #include <string>
      7 #include <vector>
      8 #include <queue>
      9 #include <set>
     10 using namespace std;
     11 
     12 #define ll long long
     13 #define eps 1e-8
     14 #define mod 21092013
     15 
     16 #define inf 0x3f3f3f3f
     17 #define maxr 110
     18 #define maxn (maxr*maxr)
     19 int n,m;
     20 int L[maxn],R[maxn],U[maxn],D[maxn],cnt;
     21 int row[maxn],col[maxn];
     22 int N[maxr],use[maxr],head[maxr];
     23 void init(){
     24     memset(head,-1,sizeof(head));
     25     memset(N,0,sizeof(N));
     26     for(int i=0;i<=m;++i){
     27         L[i]=i-1,R[i]=i+1;
     28         U[i]=D[i]=i;
     29         row[i]=0,col[i]=i;
     30     }
     31     L[0]=m,R[m]=0;
     32     cnt=m;
     33 }
     34 void remove(int x){// 删除列
     35     for(int i=D[x];i!=x;i=D[i])
     36         L[R[i]]=L[i],R[L[i]]=R[i];
     37 }
     38 void resume(int x){// 恢复列
     39     for(int i=D[x];i!=x;i=D[i])
     40         L[R[i]]=R[L[i]]=i;
     41 }
     42 int low(){
     43     int mi=maxr,idx=0;
     44     for(int i=R[0];i;i=R[i])if(N[i]<mi)mi=N[i],idx=i;
     45     return idx;
     46 }
     47 void link(int r,int c){
     48     ++N[c],++cnt;
     49     row[cnt]=r,col[cnt]=c;
     50     U[cnt]=U[c],D[cnt]=c;
     51     U[D[cnt]]=D[U[cnt]]=cnt;
     52     if(head[r]==-1)
     53         head[r]=L[cnt]=R[cnt]=cnt;
     54     else {
     55         L[cnt]=L[head[r]];
     56         R[cnt]=head[r];
     57         L[R[cnt]]=R[L[cnt]]=cnt;
     58     }
     59 }
     60 int cost[maxr];
     61 int best;
     62 int micost[maxr];
     63 int cost2(){// lower_bound
     64     int ret=0;
     65     bool del[maxn];
     66     memset(del,false,sizeof(del));
     67     for(int c=R[0];c;c=R[c]){
     68         if(!del[c]){
     69             del[c]=true;
     70             ret+=micost[c];
     71             for(int i=D[c];i!=c;i=D[i])
     72                 for(int j=R[i];j!=i;j=R[j])
     73                     del[col[j]]=true;
     74         }
     75     }
     76     return ret;
     77 }
     78 void dance(int dep,int val){
     79     if(R[0]==0){
     80         best = min(best,val);
     81         return ;
     82     }
     83     int c=low();
     84     if(c==0||val>=best)return ;
     85     if(val+cost2()>=best)return ;// important!
     86     for(int i=D[c];i!=c;i=D[i]){
     87         use[dep]=i;
     88         remove(i);
     89         for(int j=R[i];j!=i;j=R[j])remove(j);
     90         dance(dep+1,val+cost[row[i]]);
     91         for(int j=L[i];j!=i;j=L[j])resume(j);
     92         resume(i);
     93     }
     94 }
     95 
     96 int main(){
     97     //void data();data();return 0;
     98     //freopen("in.txt","r",stdin);
     99     while(~scanf("%d%d",&m,&n)){
    100         init();
    101         memset(micost,0x3f,sizeof(micost));
    102         best=0;
    103         for(int i=1;i<=n;++i){
    104             int tmp,tmp2;
    105             scanf("%d%d",cost+i,&tmp);
    106             best+=cost[i];
    107             for(int j=0;j<tmp;++j){
    108                 scanf("%d",&tmp2);
    109                 link(i,tmp2);
    110                 micost[tmp2]=min(micost[tmp2],cost[i]);
    111             }
    112         }
    113         for(int i=1;i<=m;++i)if(!N[i]){N[1]=0;break;}
    114         if(!N[1]){puts("-1");continue;}
    115         dance(0,0);
    116         printf("%d
    ",best);
    117     }
    118     return 0;
    119 }
    120 void data(){
    121     freopen("in.txt","w",stdout);
    122     puts("20 100");
    123     for(int i=0;i<100;++i)
    124         printf("%d %d %d
    ",998,1,i%20+1);
    125 }
    View Code

    想着经过这样的优化,大概之前cf那题应该可以过吧(当时是TLE 42,然后用DP过的),改了一下,SUBMIT,AC。。。超级感动的说。。。虽然比DP的要慢,但毕竟是搜索算法嘛。。。很不错了。。。DLX 600+ms(只有第60个case>15ms....别的case都<=15ms); DP 200+ms(相对较多100+ms,200+ms)。。。这篇应该不用再编辑了吧╮(╯▽╰)╭有错漏的话请观客提出=。=本人目前处于自嗨状态

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <algorithm>
      5 #include <cmath>
      6 #include <string>
      7 #include <vector>
      8 #include <queue>
      9 #include <set>
     10 using namespace std;
     11 
     12 #define ll long long
     13 #define eps 1e-8
     14 #define mod 21092013
     15 
     16 #define inf 0x3f3f3f3f
     17 #define maxr 110
     18 #define maxn (maxr*maxr)
     19 int n,m;
     20 int L[maxn],R[maxn],U[maxn],D[maxn],cnt;
     21 int row[maxn],col[maxn];
     22 int N[maxr],use[maxr],head[maxr];
     23 int monitor[maxr];
     24 int B;
     25 void init(){
     26     memset(head,-1,sizeof(head));
     27     memset(N,0,sizeof(N));
     28     for(int i=0;i<=m;++i){
     29         L[i]=i-1,R[i]=i+1;
     30         U[i]=D[i]=i;
     31         row[i]=0,col[i]=i;
     32     }
     33     L[0]=m,R[m]=0;
     34     cnt=m;
     35 }
     36 void remove(int x){// 删除列
     37     for(int i=D[x];i!=x;i=D[i])
     38         L[R[i]]=L[i],R[L[i]]=R[i];
     39 }
     40 void resume(int x){// 恢复列
     41     for(int i=D[x];i!=x;i=D[i])
     42         L[R[i]]=R[L[i]]=i;
     43 }
     44 int low(){
     45     int mi=maxr,idx=0;
     46     for(int i=R[0];i;i=R[i])if(N[i]<mi)mi=N[i],idx=i;
     47     return idx;
     48 }
     49 void link(int r,int c){
     50     ++N[c],++cnt;
     51     row[cnt]=r,col[cnt]=c;
     52     U[cnt]=U[c],D[cnt]=c;
     53     U[D[cnt]]=D[U[cnt]]=cnt;
     54     if(head[r]==-1)
     55         head[r]=L[cnt]=R[cnt]=cnt;
     56     else {
     57         L[cnt]=L[head[r]];
     58         R[cnt]=head[r];
     59         L[R[cnt]]=R[L[cnt]]=cnt;
     60     }
     61 }
     62 int cost[maxr];
     63 ll best;
     64 int micost[maxr];
     65 ll cost2(){// lower_bound
     66     ll ret=0;
     67     bool del[maxn];
     68     memset(del,false,sizeof(del));
     69     for(int c=R[0];c;c=R[c]){
     70         if(!del[c]){
     71             del[c]=true;
     72             ret+=micost[c];
     73             for(int i=D[c];i!=c;i=D[i])
     74                 for(int j=R[i];j!=i;j=R[j])
     75                     del[col[j]]=true;
     76         }
     77     }
     78     return ret;
     79 }
     80 void dance(int dep,ll val,int mak){
     81     if(R[0]==0){
     82         best = min(best,val+(ll)mak*B);
     83         return ;
     84     }
     85     int c=low();
     86     if(c==0||val+(ll)mak*B>=best)return ;
     87     if(val+(ll)mak*B+cost2()>=best)return ;// important!
     88     for(int i=D[c];i!=c;i=D[i]){
     89         use[dep]=i;
     90         remove(i);
     91         for(int j=R[i];j!=i;j=R[j])remove(j);
     92         dance(dep+1,val+cost[row[i]],max(mak,monitor[row[i]]));
     93         for(int j=L[i];j!=i;j=L[j])resume(j);
     94         resume(i);
     95     }
     96 }
     97 
     98 int main(){
     99     //void data();data();return 0;
    100     //freopen("in.txt","r",stdin);
    101     while(~scanf("%d%d%d",&n,&m,&B)){
    102         init();
    103         memset(micost,0x3f,sizeof(micost));
    104         best=0;int mam=0;
    105         for(int i=1;i<=n;++i){
    106             int tmp,tmp2;
    107             scanf("%d%d%d",cost+i,monitor+i,&tmp);
    108             best+=cost[i];
    109             mam=max(mam,monitor[i]);
    110             for(int j=0;j<tmp;++j){
    111                 scanf("%d",&tmp2);
    112                 link(i,tmp2);
    113                 micost[tmp2]=min(micost[tmp2],cost[i]);
    114             }
    115         }
    116         best+=(ll)mam*B;
    117         for(int i=1;i<=m;++i)if(!N[i]){N[1]=0;break;}
    118         if(!N[1]){puts("-1");continue;}
    119         dance(0,0,0);
    120         printf("%I64d
    ",best);
    121     }
    122     return 0;
    123 }
    124 void data(){
    125     freopen("in.txt","w",stdout);
    126     puts("20 100");
    127     for(int i=0;i<100;++i)
    128         printf("%d %d %d
    ",998,1,i%20+1);
    129 }
    View Code

    附上DP代码吧

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <cmath>
     6 #include <string>
     7 #include <vector>
     8 using namespace std;
     9 
    10 #define ll long long
    11 //#define inf 0x3f3f3f3f
    12 #define inf (1ll<<60)
    13 #define maxn 110
    14 #define mod 1000000007
    15 #define eps 1e-8
    16 
    17 
    18 struct node{
    19     int x,k,st;
    20 }p[maxn];
    21 bool cmp(node a,node b){return a.k<b.k;}
    22 ll dp[1<<20];
    23 int main(){
    24     int n,m,b,mm,tmp;
    25     while(~scanf("%d%d%d",&n,&m,&b)){
    26         for(int i=0;i<n;++i){
    27             scanf("%d%d%d",&p[i].x,&p[i].k,&mm);
    28             p[i].st=0;
    29             while(mm--){
    30                 scanf("%d",&tmp);
    31                 p[i].st+=(1<<(tmp-1));
    32             }
    33         }
    34         ll ans=inf;
    35         sort(p,p+n,cmp);
    36         for(int j=(1<<m)-1;j;--j)dp[j]=inf;
    37         dp[0]=0;
    38         for(int i=0;i<n;++i){
    39             for(int j=(1<<m)-1;j>=0;--j)
    40                 dp[j|p[i].st] = min(dp[j|p[i].st], dp[j]+p[i].x);
    41             ans = min(ans,dp[(1<<m)-1]+(ll)p[i].k*b);
    42         }
    43         if(ans==inf)puts("-1");
    44         else printf("%I64d
    ",ans);
    45     }
    46     return 0;
    47 }
    View Code
  • 相关阅读:
    关于接口和接口中多肽问题的实例
    java 简单的单例 实现
    关于动态数组的问题
    一百以内的杨辉三角
    将阿拉伯数字转为中文大写读法
    sql server 2005 优化方法
    Sql Server 2005 数据库 优秀辅助工具推荐
    SSIS高级内容 系列一
    锁定
    SQL Server 2005查询处理结构用户模式计划(UMS)
  • 原文地址:https://www.cnblogs.com/nextbin/p/3702434.html
Copyright © 2011-2022 走看看