「LuoguT36048」 Storm in Lover

Description


平成二十四年(2012年),5月11日,東京,某弓道場。

“吶,吶,海未醬,你聽說了嗎?幾天後的那場弓道大會?啊—!”橙發少女興奮地拿着一張傳單一樣的紙跑向藍髮少女。由於過於興奮,橙發在跑過大門的時候一不小心,被門檻絆了一跤。

然而,藍髮少女站立着,手上拿着弓箭,似乎她的世界裏並沒有橙發少女。

她將弓擡起。拉弓;弓滿;箭出。

可惜,離紅心偏了一點。

藍髮少女本來的激動瞬間平靜了下來,眼神彷彿有些遊離。恍惚之間,這時才注意到摔倒的橙發和她手中的傳單。

“啊……穗乃果,抱歉。我現在沒什麼心情,讓我一個人靜一會吧。”

“海未醬……”

“……事情就是這樣。繪里醬有沒有什麼能讓海未醬振作起來的方法呢?”穗乃果出來以後,碰到了她們的學生會長,絢瀨繪里,於是把海未沒有幹勁事情告訴了她。

“這的確是個問題呢。……說起來,我聽說前幾天海未常用的那把弓壞了,現在用的如果是新弓的話,或許她需要一段時間熟練一下呢。”繪里回憶了一下,提議讓海未多多練習一下新的弓。
題目描述

海未面前現在有n個靶子。按照繪里的指示,海未需要把這n個靶子全部射穿纔行。

一開始,海未的精力爲m,力度爲a。每射穿一個靶子,海未對弓的熟練度就會上升,此時力度會增加b。

每個靶子都有一個單獨的耐久度d[i],每次受到海未的攻擊,靶子的耐久度都會減少海未當前的力度的值。當靶子的耐久度爲0或0以下時,靶子被破壞。但是,如果海未在一次射箭後並沒有射穿這個靶子,海未的精力會減少c[i]。如果海未通過一次射箭破壞了靶子,她的精力不會受到影響。

海未可以自由地選擇射靶子的順序。請問,海未是否能夠通過合理地安排射靶子的順序,使得她能夠將這些靶子全部射穿?如果能,她完成任務後最多能省下多少精力?如果不能,她最多可以射穿多少個靶子?

Input


輸入的第一行爲四個正整數n,m,a,b。 接下來n行,每行兩個正整數c[i],d[i]。

Output


輸出的第一行僅包含一個字符串。請回答海未醬是否能完成全部射穿靶子的任務。 如果可以完成,輸出“Yes”。 如果不能完成,輸出“No” 。(兩者均不包括引號)

第二行僅包含一個正整數。若第一行爲“Yes”,則你應輸出所剩的最多精力值;若第一行爲“No”,則你應輸出最多能射穿的靶子數。

Sample Input


2 10 1 1
1 4
1 6

Sample Output


Yes
5

Hint


對於30%的數據,n<=6。

對於50%的數據,n<=9。

對於70%的數據,n<=14。

對於100%的數據,n<=21;1<=a,b,c,d<=32767。

題解


這種原創題 估計找到這裏來的都是學弟學妹

首先可見50%的數據是給暴搜的

然後看數據範圍以及最近被狀壓洗腦 決定像生日蛋糕一樣暴搜加鬼畜剪枝試圖A掉

如果這種組合已經出現過,並且現在沒有曾經優的話 剪掉。用二進制儲存組合,2^21問題不大

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
int c[27];
int d[27];
int n,m,a,b;
inline int read()
{
    char ch=getchar();
    int x=0;bool s=0;
    while(ch<'0'||ch>'9'){if(ch=='-')s=1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
    return s?-x:x;
}
inline void scan()
{
    n=read(),m=read(),a=read(),b=read();
    for(register int i=0;i<n;++i)
    c[i]=read(),d[i]=read();
    return;
}
int f[2100007];
int ans=0;
int last=-1,maxx=0;//last存餘量(初始化爲-1可以兼具檢測是否掃完功能) maxx存最多能打幾塊板
void search(int x)
{
    for(register int i=0;i<n;++i)
    if(!(ans&(1<<i)))
    {
        ans=ans|(1<<i);
        int mo;
        mo=d[i]%a==0?d[i]/a-1:d[i]/a;
        m-=mo*c[i];
        a+=b;
        if(x==n-1)last=max(last,m);
        else if(m<1)maxx=(m==0?max(maxx,x+1):max(maxx,x));
        else if(f[ans]<m){f[ans]=m;search(x+1);}
        a-=b;
        m+=mo*c[i];
        ans=ans^(1<<i);
    }
    return;
}
int main()
{
    scan();
    //memset(f,127,sizeof(f));
    search(0);
    if(last==-1){printf("No\n%d",maxx);return 0;}
    printf("Yes\n%d",last);
    return 0;
}

以及代碼中有很多莫名其妙的表達方法

是我跟出題人pb大爺爲了把90卡成100花了一個小時瞎幾巴亂調的

/最後還是A啦2333

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章