基本算法之枚举算法

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

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

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
原文地址:https://www.cnblogs.com/wolf940509/p/4427410.html