分析
由于数据范围非常小
我们可以有很多大胆的乱搞尝试Dijkstra + DP
我们不知道哪一天会修改路线
那我们就考虑吧所有的情况算出来
也就是Va[i][j]
表示第i
天到第j
天都使用一套方案的最短路
那么我们就可以直接枚举断点
也就是的暴力
DP
即可
时间复杂度:
(是因为边数可能会有
)
吐槽
洛谷得了一个最优解,牛客始终拿不到,Rank 1那位巨佬%%%
代码
//P1772 #include <algorithm> #include <iostream> #include <cstring> #include <queue> #include <cstdio> #include <cmath> #define LL long long #define Cl(X,Y) memset((X),(Y),sizeof(X)) #define FOR(i,A,B) for(int i=A;i<=B;i++) #define BOR(i,A,B) for(int i=A;i>=B;i--) #define Lowbit(X) (X & (-X)) #define Skip cout<<endl; #define INF 0x3f3f3f3f #define Mod 998244353 #define Rson (X<<1|1) #define Lson (X<<1) using namespace std; const int MaxN=1e2+10,MaxM=30,MaxP=1e4+10; int Day,Total,K,Side,u,v,w,Test; int Next[MaxM*MaxM],End[MaxM*MaxM],Head[MaxM],Cur,Val[MaxM*MaxM]; struct Node { int Opt,From,To; }Line[MaxP]; bool Choose[MaxM],Jud[MaxM]; int Dist[MaxM]; LL DP[MaxN],Va[MaxN][MaxN]; priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >Mine; inline void File() { freopen(".in","r",stdin); freopen(".out","w",stdout); } inline int Read() { int Temp=0; char Ch=getchar(); while(Ch>'9' || Ch<'0') { Ch=getchar(); } while(Ch>='0' && Ch<='9') { Temp=(Temp<<1)+(Temp<<3)+(Ch ^ 48); Ch=getchar(); } return Temp; } inline void Add_Edge(int From,int To,int Temp) { Next[++Cur]=Head[From]; Head[From]=Cur; End[Cur]=To; Val[Cur]=Temp; } inline void Dijkstra() { Dist[1]=0; Mine.push(make_pair(Dist[1],1)); while(!Mine.empty()) { pair<int,int>New=Mine.top(); Mine.pop(); if(Jud[New.second]) continue; Jud[New.second]=true; for(int i=Head[New.second];i;i=Next[i]) { if(!Choose[End[i]]) continue; if(New.first+Val[i]<Dist[End[i]]) { Dist[End[i]]=New.first+Val[i]; Mine.push(make_pair(Dist[End[i]],End[i])); } } } } signed main() { // File(); // ios::sync_with_stdio(false); Day=Read(); Total=Read(); K=Read(); Side=Read(); FOR(i,1,Side) { u=Read(); v=Read(); w=Read(); Add_Edge(u,v,w); Add_Edge(v,u,w); } Test=Read(); FOR(i,1,Test) { Line[i].Opt=Read(); Line[i].From=Read(); Line[i].To=Read(); } FOR(i,1,Day) FOR(j,i,Day) { Cl(Jud,false); Cl(Dist,0x3f); while(!Mine.empty()) Mine.pop(); Cl(Choose,true); FOR(k,1,Test) if(Line[k].From<=j && Line[k].To>=i) { Choose[Line[k].Opt]=false; } // Skip; // FOR(i,1,Total) cout<<"i: "<<Choose[i]<<endl; // Skip; Dijkstra(); Va[i][j]=Dist[Total]; } Cl(DP,0x3f); FOR(i,1,Day) { DP[i]=1ll*Va[1][i]*i; BOR(j,i-1,0) { DP[i]=min(DP[i],DP[j]+Va[j+1][i]*(i-j)+K); } } // FOR(i,1,Day) { FOR(j,i,Day) cout<<"i: "<<i<<" j: "<<j<<" Va: "<<Va[i][j]<<endl; } // FOR(i,0,Day) cout<<"i: "<<i<<" DP: "<<DP[i]<<endl; printf("%lld\n",DP[Day]); // cout<<DP[Day]<<endl; // fclose(stdin); // fclose(stdout); system("pause"); return 0; }