5月9日貪心考試總結
5月9日貪心考試總結
自制考試鏈接:https://www.luogu.org/contestnew/show/16837
這次考試沒有經過任何復習,我就想知道考出來是啥樣子。
遊記部分
考前inf小時:
我:“你是復習貪心還是背地生?”
GSC大佬:“當然是復習貪心了啊!”說罷,拿出了生物書。
JMR大佬:“肯定是背地生了啊!我明天肯定會爆(A)零(K)。”
文化課大佬QHY:“JMR你肯定爆(A)零(K)”
CXY大佬:“那你呢?”說罷,拿出了生物書。
果然是神仙啊%%%。
考前0.1小時:
我:“這次絕對不會考加工生產調度問題。”
YYQ大佬:“???”
我:“這次肯定要考種樹(區間選點)。”
YYQ大佬:“???”
我:“這次可能要考噴水裝置。”
YYQ大佬:“???”
果然是神仙啊%%%。
考試時:
經過我某條以腳趾為神經中樞的反射弧做出的反應,我要按順序開題。
看到T1(diet):我的天哪!不是說好考貪心的嗎???這是 ······ 什麽毒瘤東西???
境澤曰:“甚香!”
於是我去看了T2(fruit)。這不是我做過的原題嗎?使用STL幾分鐘切掉
然後我又回去看了T1。
境澤曰:“甚香!”
這不是道紅題嗎?真是尷尬。兩分鐘切了。
於是我去看了T3。
這是 ······ 噴水???完了。然後就去看了T4。
woc不是說好貪心的嗎???這是 ······ 註明了的暴搜???這題我之前好像是打表過的啊?
於是我就打了個暴搜。
數據範圍:n≤200,2≤k≤6。
於是我輸入了200 6
2.7e-4
小時過去了......
沒有輸出!!!
心態崩了,要爆零了!!!
這時,CXY說過的一句話在我腦海中閃現——
"記搜不就是有技巧的搜索嗎?"
於是我剪了個枝,好像沒有超時。於是我又去剛T3(仿佛不叫剛)
"這次肯定要考種樹(區間選點)"。
還真考到了。這不就是個種雷達嗎?於是我就切了它。
這時,GSC大佬:“我覺得T3比T4難。”
%%%果然是大佬
剩下半小時,沒有查錯,沒有對拍,而是——
和YYQ大佬頹太空彈珠???
考後:
於是 ...... 我就這樣AK了。
題解部分
T1:
這是道簽到題(至少寫完後的我是這麽認為的)。只需要把所有食物按脂肪從大到小排序,取最多脂肪的食物,然後把當前種類的可選個數的限制減一,當然,如果可選的個數為0,那就直接continue;
。這樣就可以獲得最優解了。證明略。第一題真沒什麽好說的。
代碼:
#include<iostream>
#include<cstdio>
#include<fstream>
#include<algorithm>
#include<cstring>
using namespace std;
const int MaxN=505;
int n,m,k;
int num[MaxN];
struct food {
int col,fat;
}a[MaxN];
void init()
{
freopen("diet.in","r",stdin);
freopen("diet.out","w",stdout);
}
bool cmp(food a,food b)
{
return a.fat>b.fat;
}
int main()
{
init();
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=k;i++) scanf("%d",&num[i]);
for(int i=1;i<=n;i++) scanf("%d%d",&a[i].fat,&a[i].col);
sort(a+1,a+1+n,cmp);
int cnt=0,ans=0;
for(register int i=1;i<=n;i++) {
int col=a[i].col,fat=a[i].fat;
if(num[col]>0) {
ans+=fat;
num[col]--;
cnt++;
}
if(cnt==m) break;
}
printf("%d",ans);
}
T2:
要求用優先隊列,那我們就用。這道題的策略肯定是每次選出最小的兩堆果子,合並後再排序。當然快排很浪費,是會超時的。我們使用小根堆來實現。這種水題也沒什麽好說的。
我的代碼:
#include<iostream>
#include<cstdio>
#include<queue>
#include<fstream>
using namespace std;
priority_queue<int,vector<int>,greater<int> >q;
int n;
inline void init()
{
freopen("fruit.in","r",stdin);
freopen("fruit.out","w",stdout);
}
int main()
{
init();
scanf("%d",&n);
for(int i=1;i<=n;i++) {
int x;
scanf("%d",&x);
q.push(x);
}
int ans=0;
while(q.size()>1) {
int x=q.top();q.pop();
int y=q.top();q.pop();
ans+=x+y;
q.push(x+y);
}
printf("%d",ans);
}
T3:
這題引入了平面直角坐標系,看起來比較復雜,但實際上就是板子。我們先預處理出每個島可被觀察的區間,也就是說每個區間內要求有一個雷達。這就是區間選點的板子了。板子就沒什麽好說的了。
#include<iostream>
#include<cstdio>
#include<fstream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int MaxN=1005;
struct segment {
double l,r;
}a[MaxN];
int n;
double d;
int num[MaxN];
inline double calc(double y)
{
return sqrt(d*d-y*y);
}
inline void init()
{
scanf("%d%lf",&n,&d);
for(register int i=1;i<=n;i++) {
double x,y;
scanf("%lf%lf",&x,&y);
if(y>d) {
printf("-1");
exit(0);
}
double len=calc(y);
a[i].l=x-len;
a[i].r=x+len;
num[i]=1;
}
}
bool cmp(segment x,segment y)
{
return x.r<y.r;
}
inline void work()
{
int ans=0;
sort(a+1,a+1+n,cmp);
int now=0;
for(int i=1;i<=n;i++) {
double nowr=a[i].r;
if(num[i]<=0) continue;
num[i]--;
for(register int j=i+1;j<=n;j++) {
if(a[j].l<=nowr) {
num[j]--;
}
}
ans++;
}
printf("%d",ans);
}
int main()
{
init();
work();
}
T4:
這道是老師故意出的超綱題。肯定不帶腦子暴搜是會 T 掉的(如果傻到一種境界還會WA)。首先需要判重。在暴搜剪枝中,記last是一種常見的策略。所以我們就記一個last,每次下一個數必定大於last,這樣我們搜出的組合就是單調不降的,就不會重了。然後考慮T的問題。我們發現,當下一個數過大時,就沒有保持序列單調不降的可能了。所以我們再加一個可行性剪枝,枚舉量就會大大減少了。
代碼:
#include<iostream>
#include<cstdio>
#include<fstream>
using namespace std;
int n,k;
int ans=0;
int sum=0;
inline void init()
{
freopen("divide.in","r",stdin);
freopen("divide.out","w",stdout);
}
inline void dfs(int l,int a)
{
sum++;
if(sum==k+1) {
if(a==0)
ans++;
}
else {
for(register int i=l;i<=a-i*(k-sum);i++) {
dfs(i,a-i);
}
}
sum--;
}
int main()
{
init();
scanf("%d%d",&n,&k);
dfs(1,n);
printf("%d",ans);
}
總結部分
雖然這次AK了,但仍有很多不足:
1、眼瞎。看錯了多少題意?紅題都能看成毒瘤?幸好我心態不差,不然就爆零了。
2、頹廢。寫完就頹,萬一文件錯了怎麽辦?幸好臉好,不然就爆零了。
3、急躁。寫題的時候手忙腳亂的。這樣容易寫炸。幸好我臉好,沒有炸。
1: 焦鳴睿還真爆零了
2: YYQ怎麽回事?我不是說了要考種樹嗎?
3: GSC和CXY把T3弄成了大模擬海星
5月9日貪心考試總結