zoukankan      html  css  js  c++  java
  • 基本算法之枚举算法

    最近开始重读刘汝佳的黑书,从最开始的算法开始吧,毕竟好久没搞了,废话不多说,我们来看看枚举吧

    关于枚举的说明,大家可以看看刘汝佳老师的《算法艺术及信息学竞赛》和配套课件,我就不多说了

    UVA1009

    链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=245&page=show_problem&problem=3450

    很基础的题目,但还是wa了好几次

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<string>
     5 #include<cmath>
     6 #include<vector>
     7 #include<algorithm>
     8 #include<map>
     9 using namespace std;
    10 #define pi acos(-1.0)
    11 const int maxn=15;
    12 double sx,sy,sz,fx,fy,fz,r[maxn],maxv;
    13 int n,sel[maxn],vist[maxn];
    14 struct point
    15 {
    16     double x,y,z;
    17 };
    18 point p[maxn];
    19 double dist(int a,int b)  //两点之间的距离
    20 {
    21     return sqrt((p[a].x-p[b].x)*(p[a].x-p[b].x)+(p[a].y-p[b].y)*(p[a].y-p[b].y)+(p[a].z-p[b].z)*(p[a].z-p[b].z));
    22 }
    23 double distege(int i)    //到每条边之间距离的最小值
    24 {
    25     double a,b,c;
    26     a=min(fabs(p[i].x-sx),fabs(p[i].x-fx));
    27     b=min(fabs(p[i].y-sy),fabs(p[i].y-fy));
    28     c=min(fabs(p[i].z-sz),fabs(p[i].z-fz));
    29     return min(a,min(b,c));
    30 }
    31 void distmin()  //计算距离的半径的值
    32 {
    33     double a,v=0;
    34     for(int i=0;i<n;i++)
    35     {
    36         a=distege(sel[i]);
    37         for(int j=0;j<i;j++)
    38         {
    39             a=min(a,dist(sel[i],sel[j])-r[sel[j]]);
    40         }
    41         r[sel[i]]=(a<0)? 0:a;
    42         if(a<=0)  continue;
    43         v+=(4.0/3*pi*r[sel[i]]*r[sel[i]]*r[sel[i]]);
    44     }
    45     maxv=max(maxv,v);
    46 }
    47 void dfs(int cnt)
    48 {
    49     if(cnt==n)
    50         distmin();
    51     for(int i=0;i<n;i++)
    52     {
    53         if(vist[i])  continue;
    54         sel[cnt]=i;
    55         vist[i]=1;
    56         dfs(cnt+1);
    57         vist[i]=0;
    58     }
    59 }
    60 int main()
    61 {
    62     int te=1;
    63     while(cin>>n)
    64     {
    65         if(n==0)   break;
    66         cin>>sx>>sy>>sz>>fx>>fy>>fz;
    67         for(int i=0;i<n;i++)
    68             cin>>p[i].x>>p[i].y>>p[i].z;
    69             maxv=0;
    70         memset(vist,0,sizeof(vist));
    71         dfs(0);
    72         printf("Box %d: %.0lf
    
    ",te++,((fabs((sx-fx)*(sy-fy)*(sz-fz)))-maxv));
    73     }
    74     return 0;
    75 }
    View Code

    枚举+DP(01背包问题)

    Tyvj1013

    链接:http://www.tyvj.cn/p/1013

    这题要同时考虑两个方面,一方面是要找到的MM最多,同时又需要花费的时间最少,开了一个三维数组,直接进行DP,裸裸的01背包

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<string>
     6 #include<vector>
     7 #include<algorithm>
     8 #include<map>
     9 using namespace std;
    10 const int maxn=100+1;
    11 int rmb[maxn],rp[maxn],time0[maxn];
    12 int n,m,r;
    13 struct point
    14 {
    15     int sum,time0;
    16 };
    17 point p[maxn][maxn];
    18 int main()
    19 {
    20     int n;
    21     while(cin>>n)
    22     {
    23         memset(p,0,sizeof(p));
    24         for(int i=1;i<=n;i++)
    25             cin>>rmb[i]>>rp[i]>>time0[i];
    26         cin>>m>>r;
    27         for(int i=1;i<=n;i++)
    28         {
    29             for(int j=m;j>=rmb[i];j--)
    30             {
    31                 for(int k=r;k>=rp[i];k--)
    32                 {
    33                     if(p[j][k].sum>p[j-rmb[i]][k-rp[i]].sum+1)
    34                     {
    35                         p[j][k].sum=p[j][k].sum;
    36                         p[j][k].time0=p[j][k].time0;
    37                     }
    38                     else if(p[j][k].sum<p[j-rmb[i]][k-rp[i]].sum+1)
    39                     {
    40                         p[j][k].sum=p[j-rmb[i]][k-rp[i]].sum+1;
    41                         p[j][k].time0=p[j-rmb[i]][k-rp[i]].time0+time0[i];
    42                     }
    43                     else
    44                     {
    45                         p[j][k].sum=p[j][k].sum;
    46                         if(p[j][k].time0>p[j-rmb[i]][k-rp[i]].time0+time0[i])
    47                             p[j][k].time0=p[j-rmb[i]][k-rp[i]].time0+time0[i];
    48                     }
    49                 }
    50             }
    51         }
    52         cout<<p[m][r].time0<<endl;
    53     }
    54     return 0;
    55 }
    View Code

    恶心枚举:

           这可能是我至今为止做的最恶心的一道枚举题了,果然黑书就是与众不同啊,刘汝佳大牛的题目第二道题目就卡了我三天,其实并没有做出来,只是阅读懂了那份代码

    没有其他理由,就是自己太弱了,为了研一能去打最后一次区域赛,必须好好努力了,真的太菜了,但最后不得不说,黑书果然是算法之王,经典中的经典

    链接:http://poj.org/problem?id=1116

    题意:

    鲁滨逊在一个遥远的孤岛上独自生活。一天,一艘装载着许多珍贵图书的轮船在岛附近失事。通常在这种情况下,罗宾逊会把船上有用的东西从残骸里抢救出来运到他住的岛上。这一次,他带回来了一箱书。 有了这些书,鲁滨逊决定做一个书架,进而建立自己的藏书室。他在石头墙上凿了一个矩形壁龛, 把一些栓钉入墙体,然后找来一些木板分别架在两个水平的栓子上做成书架。 不巧的是,鲁滨逊忽然发现有一本珍贵的旧书特别大,根本无法放进他现在架好的书架里。他仔细量了一下这本大部头的高和厚,想改造一下他的书架,以便于把这本书也放进去(别忘了,书架是做在墙里面的,不能超出范围)。下面是一些改造的操作方法: 把架子留在原地不动; 把木板向左移或者向右移; 把木板锯掉一段后向左或向右移; 把栓子钉到与原来位置处于同一水平线的另一个位置,并把木板左移或者右移; 把木板锯掉一段,移动某一个栓子到同一个水平线上另一个位置,并把木板左移或者右移; 把木板和两个栓子一起拿掉。 当木板被两个栓子架住,并且木板的中心在两个栓子之间或恰在一个栓子上方时,这个书架的放置是稳定的。鲁滨逊开始设计的藏书室里所有的书架都是稳定放置的。木板的长度都是整数,单位是英寸。他只能做到以英寸的精度切割木板,因为他的测量工具不够精确。在你的改造中,所有的书架必须始终是稳定放置的。 你要找到一个方案来改造鲁滨逊的藏书室,以便于把那本古老的大书放进去,而且要使改动尽量的少。你要尽量减少移动的栓子数目(操作4、5每次移动一个栓子,操作6每次移动两个)。如果有几种不同的办法达到这个要求,那么你要在其中找到浪费木板长度最小的一个方案(操作3、5各切割掉一定长度,操作6把整个木板的长度都浪费了)。木板的厚度和栓子的直径忽略不计。 那本大书只能竖直放置,它的全部厚度都要位于木板上,而且只可以碰到其它木板或栓子的边缘。
    输入 输入文件的第一行有四个整型数XN,YN,XT,YT,用空格隔开。他们代表了壁龛的宽和高,以及大书的厚和高,单位为英寸(1 <= XN, YN, XT, YT <= 1000). 输入文件的第二行有一个整型数N(1 <= N <= 100)代表了书架的数量。下面的N行每行都给出一个架子的信息。每行的五个整型数yi, xi, li, x1i, x2i用空格隔开,其中:yi (0 < yi < YN) 表示第i个架子距离壁龛底部的高度;xi (0 <= xi < XN) 表示第i个架子木板左端到壁龛左边的距离;li (0 < li <= XN - xi) 表示第i个架子木板的长度;x1i (0 <= x1i <= li/2) 表示第i个架子木板左端到支撑它的左边一个栓子的距离;x2i (li/2 <= x2i <= li; x1i < x2i) 表示第i个架子木板左端到右面一个栓子的距离,以上所有数据的单位都是英寸。 所有的架子都位于不同的高度并且放置稳定。所有输入数据一定有解。
    输出 输出文件中应包含两个整型数,中间用一个空格隔开。第一个是要移动的栓子数目的最小值,第二个是按照这个方案要浪费掉的木板总长的最小值。
    input: 11 8 4 6
    4
    1 1 7 1 4
    4 3 7 1 6
    7 2 6 3 4
    2 0 3 0 3
    output: 1 3

    下面贴上自己看懂之后加上注释的代码:

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cmath>
      5 #include<string>
      6 #include<vector>
      7 #include<algorithm>
      8 #include<map>
      9 #include<stack>
     10 #include<queue>
     11 using namespace std;
     12 const int maxn=100+10;
     13 struct point
     14 {
     15     int y,x,len,x1,x2;
     16 };
     17 point a[maxn];
     18 int xn,Yn,xt,yt;
     19 int n;
     20 int optPegs=20000,optCost=10000;
     21 
     22 //按照y从小到大进行排序
     23 bool cmp(point p1,point p2)
     24 {
     25     return p1.y<p2.y;
     26 }
     27 
     28 //放在第k块木板上的书,起始位置为x,栓子的最小移动数量及在满足此条件下的木板最小削去长度
     29 void check(int k,int x,int &minPegs,int &minCost)
     30 {
     31     for(int i=k+1;i<n;i++)
     32     {
     33         //排除两种不会阻挡的情况
     34         if(a[i].y>=a[k].y+yt) break;
     35         if(a[i].x+a[i].len<=x||a[i].x>=x+xt);
     36 
     37         //当书的起始位置大于x2时
     38         else if(a[i].x2<=x)
     39         {
     40             int mx;
     41             if(x-a[i].x1<=a[i].x1) mx=2*(x-a[i].x1);
     42             else mx=x;
     43             if(mx<a[i].len) minCost+=a[i].len-mx;
     44         }
     45 
     46         //当x1大于书的结束位置时
     47         else if(a[i].x1>=x+xt)
     48         {
     49             int mx;
     50             if(a[i].x2-(x+xt)<=xn-a[i].x2)  mx=2*(a[i].x2-(x+xt));
     51             else mx=xn-(x+xt);
     52             if(mx<a[i].len)  minCost+=a[i].len-mx;
     53         }
     54 
     55         //起始位置大于x1,小于x2,结束位置大于x2
     56         else if(a[i].x1<=x&&a[i].x2>x&&a[i].x2<x+xt)
     57         {
     58             if(x==0)
     59             {
     60                 minPegs+=2;
     61                 minCost+=a[i].len;
     62             }
     63             else
     64             {
     65                 minPegs++;
     66                 if(a[i].len>x)
     67                     minCost+=a[i].len-x;
     68             }
     69         }
     70 
     71         //起始位置小于x1,终止位置在x1与x2之间
     72         else if(a[i].x1>x&&a[i].x1<x+xt&&a[i].x2>=x+xt)
     73         {
     74             if(x+xt==xn)
     75             {
     76                 minPegs+=2;
     77                 minCost+=a[i].len;
     78             }
     79             else
     80             {
     81                 minPegs++;
     82                 if(a[i].len>xn-(x+xt))
     83                     minCost+=a[i].len-(xn-(x+xt));
     84             }
     85         }
     86 
     87         //起始位置大于x1,终止位置小于x2
     88         else if(a[i].x1<=x&&a[i].x2>=x+xt)
     89         {
     90             if(x==0&&xt==xn)  minPegs+=2;
     91             else  minPegs++;
     92             int mx=x>xn-(x+xt) ? x:xn-(x+xt);
     93             if(a[i].len>mx)  minCost+=a[i].len-mx;
     94         }
     95 
     96         //起始位置小于X1,终止位置大于X2
     97         else if(a[i].x1>x&&a[i].x2<x+xt)
     98         {
     99             minPegs+=2;
    100             minCost+=a[i].len;
    101         }
    102     }
    103 }
    104 
    105 //解决书在第k块木板上的放置问题
    106 void solve(int k)
    107 {
    108     for(int book_l=0;book_l+xt<=xn;book_l++)
    109     {
    110         int minPegs=0,minCost=0;
    111         if(book_l+a[k].len<a[k].x1)  continue;
    112         if(a[k].x2+a[k].len<book_l+xt)  break;
    113         if(book_l+a[k].len<a[k].x1||a[k].x2+a[k].len<book_l+xt)  continue;
    114         if(2*(a[k].x1-book_l)>a[k].len||2*(book_l+xt-a[k].x2)>a[k].len)
    115             minPegs++;
    116         else if(a[k].x2-book_l>a[k].len||(book_l+xt)-a[k].x1>a[k].len)
    117             minPegs++;
    118         check(k,book_l,minPegs,minCost);
    119         if(minPegs<optPegs||(minPegs==optPegs&&minCost<optCost))
    120         {
    121             optPegs=minPegs;
    122             optCost=minCost;
    123         }
    124     }
    125 }
    126 int main()
    127 {
    128     while(cin>>xn>>Yn>>xt>>yt)
    129     {
    130         cin>>n;
    131         for(int i=0;i<n;i++)
    132         {
    133             cin>>a[i].y>>a[i].x>>a[i].len>>a[i].x1>>a[i].x2;
    134             a[i].x1+=a[i].x;
    135             a[i].x2+=a[i].x;
    136         }
    137         sort(a,a+n,cmp);
    138         for(int i=0;i<n;i++)
    139         {
    140             if(a[i].y+yt>Yn)  break;
    141             if(a[i].len>=xt)  solve(i);
    142         }
    143         cout<<optPegs<<" "<<optCost<<endl;
    144     }
    145     return 0;
    146 }
    View Code
  • 相关阅读:
    C# 窗体(登录界面)
    PHP中include与require的特点和区别说明
    PHP面对对象7大原则
    PHP设计模式 单例模式与工厂模式
    PHP面向对象总结 及 静态 抽象 接口
    PHP面向对象解析
    php常用函数整理
    PHP基础(二) 1、随机数和时间 2、字符串函数
    PHP基础(一) 数组
    php 数据库的增删改查
  • 原文地址:https://www.cnblogs.com/wolf940509/p/4427410.html
Copyright © 2011-2022 走看看