基本算法之枚舉算法


最近開始重讀劉汝佳的黑書,從最開始的算法開始吧,畢竟好久沒搞了,廢話不多說,我們來看看枚舉吧

關於枚舉的說明,大家可以看看劉汝佳老師的《算法藝術及信息學競賽》和配套課件,我就不多說了

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\n\n",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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM