GalaxyOJ-988 (套路建圖+最短路)

題目

HDU陽光長跑
題目描述
數據範圍

分析

題解

程序

#include <cstdio>
#include <algorithm>
#include <cstring>
#define Add(x,y,z) (to[++num]=head[x],head[x]=num,V[num]=y,W[num]=z)
#define For(x) for(ll h=head[x],o=V[h],w=W[h]; h; o=V[h=to[h]],w=W[h])
using namespace std;
typedef long long ll;
ll head[5],to[10],V[10],W[10],num;
ll dis[5][60005];           //dis[i][j] 從2開始到 i 路徑長模爲 j 的最短路徑 
ll d12,d23,d34,d41,K,Ha,k,l,r,f[5][60005],ans=9223372036854775807ll;
struct zzk{int x,v;} q[1000000];
void SPFA(){
    memset(dis,0x7f7f7f7f,sizeof(dis));
    dis[2][0]=0,f[2][0]=0;
    for (q[l=r=0]=(zzk){2,0}; l<=r; l++){
        For(q[l].x) if (dis[o][(q[l].v+w)%Ha]>dis[q[l].x][q[l].v]+w){
            dis[o][(q[l].v+w)%Ha]=dis[q[l].x][q[l].v]+w;
            if (!f[o][(q[l].v+w)%Ha]){
                q[++r]=(zzk){o,(q[l].v+w)%Ha};
                f[o][(q[l].v+w)%Ha]=1;
            }
        }
        f[q[l].x][q[l].v]=0;
    }
}

void debug(){
    for (ll i=1; i<=4; i++) {
        For(i) printf("(%d %d) ",o,w);
        puts("");
    }
}

int main(){
    scanf("%lld%lld%lld%lld%lld",&K,&d12,&d23,&d34,&d41);
    Add(1,2,d12),Add(2,1,d12),Add(2,3,d23),Add(3,2,d23),Add(3,4,d34),Add(4,3,d34),Add(4,1,d41),Add(1,4,d41);
    Ha=min(d12,d23)*2;
    SPFA();
    for (ll i=0; i<Ha; i++){
        k=dis[2][i];
        if (k>K) {ans=min(k,ans); continue;}
        k+=(K-k)/Ha*Ha;
        if (k<K) k+=Ha;
        ans=min(k,ans);
    }
    printf("%lld",ans);
}

提示

  • 這是一種經典的套路題,(給幾種數,問湊成不小於 K 的最小和是多少)
  • 咋一看似乎是數論,實際上卻是通過建圖再跑個最短路巧妙解決,這個方法真的值得積累。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章