zoukankan      html  css  js  c++  java
  • TYVJ 1866状压DP

    内存优化版(100分):

    View Code
     1 #include <cstdio>
     2 #include <cstdlib>
     3 using namespace std;
     4 const int N=19;
     5 __int64 dp[1<<N][N],ans;int n,m,st;
     6 bool map[N][N],mp[N]; 
     7 void read()
     8 {
     9     scanf("%d%d",&n,&m);
    10     for(int i=1,a,b;i<=m;i++)
    11     {
    12         scanf("%d%d",&a,&b);
    13         a-=2;b-=2;
    14         if(a<0) mp[b]=true;//与-1号点连接的点 
    15         else if(b<0) mp[a]=true;
    16         else map[a][b]=map[b][a]=true;
    17     }
    18     n--;
    19 }
    20 void special()
    21 {
    22     //预先算出包含第一个点(称这个点为-1号点)的方案,节约空间
    23     for(int i=0;i<n;i++) 
    24         if(mp[i]) dp[1<<i][i]=1;
    25     for(int i=0;i<(1<<n);i++)
    26         for(int j=0;j<n;j++)//枚举终点 
    27         {
    28             if(!dp[i][j]) continue;//要求存在dp[i][j]
    29             if((i&(1<<j)))  //要求i包含j点 ,j是结尾 
    30             {
    31                 if(mp[j]&&i-(1<<j)>0)//-1和j有边 ,>=3条边 
    32                     ans+=dp[i][j];
    33                 for(int k=0;k<n;k++)//拓展链 
    34                     if((!(i&(1<<k)))&&map[k][j])//k不在i中 ,k,j有边 
    35                         dp[i|(1<<k)][k]+=dp[i][j];
    36             }
    37         }
    38 }
    39 void go()
    40 {
    41     for(int i=0;i<(1<<n);i++)
    42         for(int j=0;j<n;j++)
    43             dp[i][j]=0; 
    44     for(int i=0;i<n;i++) dp[1<<i][i]=1;
    45     for(int i=0;i<(1<<n);i++)
    46     {
    47         for(int j=0;j<n;j++)//结尾 
    48         {
    49             if(!dp[i][j]) continue;
    50             st=-1;//标志是否找到最小起点 
    51             for(int k=0;k<n;k++)//最小开头 
    52             {
    53                 if(i&(1<<k))
    54                 {
    55                     st=k;
    56                     if(map[j][k]&&i>(1<<k)+(1<<j))//j,k相连,>=3条边
    57                         ans+=dp[i][j];
    58                     break;
    59                 }
    60             }
    61             if(st!=-1)
    62             {
    63                 for(int k=st+1;k<n;k++)
    64                 {
    65                     if(!(i&(1<<k))&&map[k][j])//不在i中,且和结尾有边 
    66                     {
    67                         dp[i|(1<<k)][k]+=dp[i][j];
    68                     }
    69                 }
    70             }
    71         }
    72     }
    73     printf("%I64d",ans>>1); //顺时针逆时针有重复 
    74 }
    75 int main()
    76 {
    77     read();
    78     special();
    79     go();
    80     system("pause");
    81     return 0;
    82 }

    MLE版(long long改成__int64可以得到90分):

    View Code
     1 #include <cstdio>
     2 #include <cstdlib>
     3 using namespace std;
     4 const int N=20;
     5 long long dp[1<<N][N],ans;int n,m,st;
     6 bool map[N][N]; 
     7 void read()
     8 {
     9     scanf("%d%d",&n,&m);
    10     for(int i=1,a,b;i<=m;i++)
    11     {
    12         scanf("%d%d",&a,&b);
    13         a--;b--;
    14         map[a][b]=map[b][a]=true;
    15     }
    16 }
    17 void go()
    18 {
    19     for(int i=0;i<n;i++) dp[1<<i][i]=1;
    20     for(int i=0;i<(1<<n);i++)
    21     {
    22         //printf("%lld\n",i);
    23         for(int j=0;j<n;j++)//结尾 
    24         {
    25             if(!dp[i][j]) continue;
    26             st=-1;
    27             for(int k=0;k<n;k++)//最小开头 
    28             {
    29                 if(i&(1<<k))
    30                 {
    31                     st=k;
    32                     if(map[j][k]&&i>(1<<k)+(1<<j))
    33                     {    
    34                         ans+=dp[i][j];
    35                     }
    36                     break;
    37                 }
    38             }
    39             if(st!=-1)
    40             {
    41                 for(int k=st+1;k<n;k++)
    42                 {
    43                     if(!(i&(1<<k))&&map[k][j])//不在i中,且和结尾有边 
    44                     {
    45                         dp[i|(1<<k)][k]+=dp[i][j];
    46                     }
    47                 }
    48             }
    49         }
    50     }
    51     printf("%lld\n",ans>>1); 
    52 }
    53 int main()
    54 {
    55     read();
    56     go();
    57     system("pause");
    58     return 0;
    59 }
    没有人能阻止我前进的步伐,除了我自己!
  • 相关阅读:
    AutoCAD利用VBA设置线型和添加用户自定义线性
    AutoVBA利用for循环创建同心圆弧
    AutoVBA利用Hacth对象填充图元对象
    AutoVBA利用AddArc方法创建Arc对象
    2011年6月5日星期天
    AutoVBA控件的tabindex和tabstop属性及with语句
    AutoVBA在绘图空间创建直线对象
    AutoVBA利用toolbar创建自己的工具栏
    AutoVBA调用AddCricle方法绘制圆
    AutoCAD利用VBA宏绘制多重平行线
  • 原文地址:https://www.cnblogs.com/proverbs/p/2647264.html
Copyright © 2011-2022 走看看