Luogu P1171 售貨員的難題

Luogu P1171 售貨員的難題

這是一道很悲傷的搜索題。。。
充分體現我多麼菜。。。
爲什麼會開始做這道題。。。因爲對面的(新招的初二的)刷caioj刷到這一題了
當我在luogu找到後一看是藍題好慌啊qwq,他們已經這麼強了嗎。。
不過luogu的數據加強了,lhy和我說caioj上的只要暴搜什麼優化不加就可以(大概就是這裏的40分的超級裸的暴搜橙題的樣子)
於是我覺得要目標遠大一點,所以我決定要A掉luogu這裏的
5.16中午
打了一中午才20.。。
明明是傻逼題啊。。。
。。。都怪今天頭疼(其實是自己弱)
5.17中午
發現 昨天的思路有BUG於是重構
40還有BUG 。。。
我的40好像還不太一樣是因爲思路錯了。。。
重構終於80了
我好菜啊,這麼簡單,我爲什麼繞了那麼久。。。
5.18中午
還得剪枝優化。。。
容易想到一個似乎不太可行的方法,排序,按邊排
打了,結果十分可行啊90了QWQ
還有最後一點啊。。。
5.19晚上
(本來今天上luogu是來月賽的,結果發現我記錯時間已經開始1h了,
然後又發現月賽502了於是想想還不如來A這道題吧)
想到lhy週五和我說的,卡常
於是我開始看卡常技巧的blog,把我所有覺得可行的都堆了上去。。。
卡來卡去差不多啊!!
90還是90!!
無可奈何花落去,我點開了一篇題解,我發現思路和我一樣(我怎麼就A不了!!。。。)
但它多了一個向外連最小的邊的數組,如果這條邊都不行就都不行,以及先建邊再直接排序
於是我把把先暫時儲存排序後建邊改成先建邊再直接排序
最小邊那個也依葫蘆畫瓢打上了(仔細想想並沒有用啊,因爲已經排序了)
還是90!!
怎麼辦吶。。。
我點開了luogu的題解
!!!!!!!!!!!我要把這個標的比標題還要大

if(sum+(n-t)+1>=ans)return 0;

就是這個優化,本來我第三個點T了,是1.5s左右的
然後加了這句第三個點0ms,心情複雜。。。

長長的 卡常和調試。。。

#include<cstdio>
#include<cstring>

int n,ans,b[110],c[110][110],road[1010],len,lenn,first[10100],s[10100],z,minn[110];
struct nod1{int x,y,c,next;}a[10010],d[10010];

inline void read(int &x)
{
    register int f=1;
    x=0;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    x*=f;
}

inline void print(int x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9)
        print(x/10);
    putchar(x%10+'0');
}

inline int kp(int l,int r)
{
    register int x=l,y=r,m=a[(x+y)/2].c;
    while(x<=y)
    {
        while(a[x].c<m)x++;
        while(a[y].c>m)y--;
        if(x<=y)
        {
            nod1 t=a[x];a[x]=a[y];a[y]=t;
            x++;y--;
        }
    }
    if(l<y)kp(l,y);
    if(x<r)kp(x,r);
}

/*inline int ins(int x,int y,int c)
{
    len++;
    a[len].x=x;
    a[len].y=y;
    a[len].c=c;
    a[len].next=first[x];
    first[x]=len;
}*/

inline int dfs(int x,int sum,int t)
{
    //printf("%d %d %d |\n",x,sum,t);
    if(sum>ans)return 0;
    if(t==n)
    {
        /*for(int i=1;i<=n;++i)
        {
            printf("%d ",road[i]);
        }printf("|%d | %d | %d\n",road[t-1],s[road[t-1]],sum);*/
        if(sum+s[road[t-1]]<ans)ans=sum+s[road[t-1]];
        return 0;
    }
    for(register int i=d[x].x+1;i<=d[x].y;++i)
    {
        register int y=a[i].y;
        //if(x!=y)
        //{
            //printf("1111");
            if(a[i].c+sum>=ans)return 0; 
            if(sum+(n-t)+1>=ans)return 0;
            //printf("3333");
            if(b[y]==0&&sum+a[i].c+z-minn[y]<ans&&a[i].c)
            {
                //printf("2222");
                b[y]=1;road[t]=y;
                z-=minn[y];
                dfs(y,sum+a[i].c,t+1);
                z+=minn[y];
                b[y]=0;road[t]=0;
            //}
        }   
    }
}

int main()
{
    read(n);
    for(register int i=1;i<=n;++i)
    {
        d[i].x=lenn+1;
        for(register int j=1;j<=n;++j)
        {

            //scanf("%d",&d[j].c);
            len++;
            a[len].x=i;
            a[len].y=j;        
            read(a[len].c); 
            //d[j].y=j;
            ans+=a[len].c;
            if(j==1)
            {
                s[i]=a[len].c;
            }
            if(minn[i]>a[len].c&&i!=j)minn[i]=a[len].c; 
        }
        d[i].y=len;
        z+=minn[i];
        kp(lenn+1,len);//ok
        /*for(register int j=lenn+1;j<=len;++j)
        {
            printf("%d %d %d\n",a[j].x,a[j].y,a[j].c);
        }
        printf("%d %d\n",d[i].x,d[i].y ); */
        lenn=len;
    }
    b[1]=1;
    dfs(1,0,1);
    print(ans);
} 

第一次大規模卡常。。。以前最多寫讀優或者點luogu的O2
以後要卡常,可以來看自己這個很亂的代碼qwq

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