zoukankan      html  css  js  c++  java
  • HDU 5727 Necklace

    题目:Necklace

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=5727

    题意:要用n个阳石和n个阴石来串一个项链(环状),规定阳石旁边只能是阴石,阴石旁只能是阳石,现在有m对特殊阴阳石,这些阴阳石相邻会使得阳石出故障(照样可以用),问串这个项链,至少有几个故障的阳石。

    思路:

      看到题目的瞬间,莫名奇妙地就想到了二分图(阴石和阳石两个集合,又要求阴阳交错着放),有个变通就是最后并不是阴石匹配阳石,而是阳石去匹配位置,看最多几个位置能放上阳石...

      我们可以先枚举所有的阴石排法(全排列),然后用二维数组s来表示阳石i可以放在哪些位置,s[i][j]=1表示阳石i可以放在j处,前提是j的两旁没有克制阳石i的阴石。这样,位置和阳石就成了两个集合,我们要做的就是让尽量多的位置放了阳石,(这种阴石排法最终故障数就是n-位置数(最大匹配数))。这道题时间卡得很紧,有一个很重要的剪枝就是全排列过程中如果最终故障数已经为0,就return吧,就不要再尝试新的排法了。

      我的代码是勉强过的,有待改进,看到网上有个自动全排列的函数next_permutation,准备去学下,我试过,比自己深搜递归快,下面两个版本,第一个1400ms左右,第二个200ms左右,快太多了,(除了本身快以外,我还少排了一个数,因为项链是一个环,所以完全可以固定一个数的位置,这样就少了一级。)

     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 #include<string.h>
     4 #include<vector>
     5 using namespace std;
     6 int n,m,maxt;
     7 int mp[12][12];
     8 vector<int> s[12];
     9 int b[12];
    10 bool u[12];
    11 bool find(int x)
    12 {
    13   if(u[x]) return false;
    14   u[x]=1;
    15   for(int j=0;j<s[x].size();j++)
    16   {
    17     int i=s[x][j];
    18     if(b[i]==0||find(b[i]))
    19     {
    20       b[i]=x;
    21       return true;
    22     }
    23   }
    24   return false;
    25 }
    26 void solve()
    27 {
    28   memset(b,0,sizeof(b));
    29   int co=0;
    30   for(int i=1;i<=n;i++)
    31   {
    32     memset(u,0,sizeof(u));
    33     if(find(i)) co++;
    34   }
    35   if(co>maxt) maxt=co;
    36 }
    37 bool v[12];
    38 int aa[12];
    39 void dfs(int ceng)
    40 {
    41   if(ceng==n)
    42   {
    43     for(int i=1;i<=n;i++) s[i].clear();
    44     for(int i=0;i<n;i++)
    45     {
    46       int k=aa[i],kk=aa[(i-1+n)%n];
    47       for(int j=1;j<=n;j++)
    48       {
    49         if(mp[k][j]==-1&&mp[kk][j]==-1) s[j].push_back(i);
    50       }
    51     }
    52     solve();
    53     return ;
    54   }
    55   for(int i=1;i<=n&&maxt!=n;i++)
    56   {
    57     if(v[i]==1) continue;
    58     v[i]=1;
    59     aa[ceng]=i;
    60     dfs(ceng+1);
    61     v[i]=0;
    62   }
    63 }
    64 int main()
    65 {
    66   int x,y;
    67   while(scanf("%d%d",&n,&m)!=EOF)
    68   {
    69     maxt=0;
    70     memset(mp,-1,sizeof(mp));
    71     while(m--)
    72     {
    73       scanf("%d%d",&x,&y);
    74       mp[y][x]=0;
    75     }
    76     memset(v,0,sizeof(v));
    77     dfs(0);
    78     printf("%d
    ",n-maxt);
    79   }
    80   return 0;
    81 }
     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 #include<string.h>
     4 #include<vector>
     5 #include<algorithm>
     6 using namespace std;
     7 int n,m,maxt;
     8 int mp[12][12];
     9 vector<int> s[12];
    10 int b[12];
    11 bool u[12];
    12 bool find(int x)
    13 {
    14   if(u[x]) return false;
    15   u[x]=1;
    16   for(int j=0;j<s[x].size();j++)
    17   {
    18     int i=s[x][j];
    19     if(b[i]==0||find(b[i]))
    20     {
    21       b[i]=x;
    22       return true;
    23     }
    24   }
    25   return false;
    26 }
    27 void solve()
    28 {
    29   memset(b,0,sizeof(b));
    30   int co=0;
    31   for(int i=1;i<=n;i++)
    32   {
    33     memset(u,0,sizeof(u));
    34     if(find(i)) co++;
    35   }
    36   if(co>maxt) maxt=co;
    37 }
    38 bool v[12];
    39 int aa[12];
    40 void dfs(int ceng)
    41 {
    42   for(int i=0;i<n;i++)
    43   {
    44     aa[i]=i+1;
    45   }
    46   do
    47   {
    48     for(int i=1;i<=n;i++) s[i].clear();
    49     for(int i=0;i<n;i++)
    50     {
    51       int k=aa[i],kk=aa[(i-1+n)%n];
    52       for(int j=1;j<=n;j++)
    53       {
    54         if(mp[k][j]==-1&&mp[kk][j]==-1) s[j].push_back(i);
    55       }
    56     }
    57     solve();
    58   }while(next_permutation(aa+1,aa+n)&&maxt!=n);
    59 }
    60 int main()
    61 {
    62   int x,y;
    63   while(scanf("%d%d",&n,&m)!=EOF)
    64   {
    65     maxt=0;
    66     memset(mp,-1,sizeof(mp));
    67     while(m--)
    68     {
    69       scanf("%d%d",&x,&y);
    70       mp[y][x]=0;
    71     }
    72     memset(v,0,sizeof(v));
    73     dfs(0);
    74     printf("%d
    ",n-maxt);
    75   }
    76   return 0;
    77 }
    用了next_permutation
  • 相关阅读:
    关于region Of interstROI
    二值图贴标签算法
    最大方差阈值分割OTSU
    已知空间N点坐标求圆心坐标,半径
    Blob Analysis Blob 分析
    前言
    Go基础学习
    Hive(数据仓库工具)
    Could not transfer artifact XXX,transfer failed for XXX 解决方案
    Docker
  • 原文地址:https://www.cnblogs.com/hchlqlz-oj-mrj/p/5690008.html
Copyright © 2011-2022 走看看