1. 程式人生 > >清北學堂模擬賽d1t5 拍照(photo)

清北學堂模擬賽d1t5 拍照(photo)

貪心 ret 如果 寬度 數學 out tdi 題目 space

題目描述
假設這是一個二次元。
LYK召集了n個小夥伴一起來拍照。他們分別有自己的身高Hi和寬度Wi。
為了放下這個照片並且每個小夥伴都完整的露出來,必須需要一個寬度為ΣWi,長度為max{Hi}的相框。(因為不能疊羅漢)。
LYK為了節省相框的空間,它有了絕妙的idea,讓部分人躺著!一個人躺著相當於是身高變成了Wi,寬度變成了Hi。但是很多人躺著不好看,於是LYK規定最多只有n/2個人躺著。(也就是說當n=3時最多只有1個人躺著,當n=4時最多只有2個人躺著)
LYK現在想問你,當其中部分人躺著後,相框的面積最少是多少。

輸入格式(photo.in)
第一行一個數n。
接下來n行,每行兩個數分別是Wi,Hi。

輸出格式(photo.out)
你需要輸出這個相框的面積最少是多少。

輸入樣例
3
3 1
2 2
4 3

輸出樣例
21

樣例解釋
如果沒人躺過來,需要27的面積。
我們只要讓第1個人躺過來,就只需要21的面積!

對於30%的數據n<=10。
對於60%的數據n<=1000,Wi,Hi<=10。
對於100%的數據1<=n,Wi,Hi<=1000。

分析:陷入了dp的死胡同.......以為就是一個三維dp,結果復雜度爆表了,正解竟然是貪心......

其實正解是貪心也很正常,數據這麽大能做到這麽快求解的也就只有貪心和數學方法了.那麽要怎麽貪心呢?因為每次旋轉一個人都要涉及到高度和長度的變化,我們人為限定一個高度.枚舉這個高度i,

如果h > i && w <= i必須躺
如果h <= i && w > i不能躺
如果h <= i && w <= i
如果h >= w,不躺
如果h < w,躺,並且將w - h排序,將剩下沒有用完的次數給用完就可以了.

思路比較巧,也有很多實用的技巧,如果對於高度和寬度的變化不好把控,人為規定一個高度就行了.數據比較大有一定可能是貪心題.

#include <cstdio>
#include <cstring>
#include <iostream>
#include 
<algorithm> using namespace std; const int inf = 0x7fffffff; int n, w[1010], h[1010], ans = inf,cnt,tot,e[1010]; bool cmp(int a, int b) { return a > b; } int main() { scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d%d", &w[i], &h[i]); for (int maxn = 1; maxn <= 1000; maxn++) { bool flag = false; int sum = 0; cnt = tot = 0; for (int i = 1; i <= n; i++) { if (h[i] > maxn && w[i] > maxn) { flag = 1; break; } if (h[i] > maxn && w[i] <= maxn) { cnt++; sum += h[i]; } else if (h[i] <= maxn && (w[i] > maxn || h[i] >= w[i])) sum += w[i]; else if (h[i] <= maxn && w[i] <= maxn && h[i] < w[i]) { e[++tot] = w[i] - h[i]; sum += w[i]; } } if (flag) continue; if (cnt > n / 2) continue; sort(e + 1, e + 1 + tot, cmp); for (int i = 1; i <= min(n / 2-cnt,tot); i++) sum -= e[i]; ans = min(ans, sum * maxn); } printf("%d\n", ans); return 0; }

清北學堂模擬賽d1t5 拍照(photo)