首页 > 代码库 > bzoj1003题解

bzoj1003题解

【题意分析】

  给你一张无向图,固定起点和终点,除这两点外每个点都有可能消失一段时间(保证起点和终点相互可达),每天选择的路径总长,以及对路径的修改都有代价,求给定时间内最小代价保证起点终点始终连通。

【解题思路】

  此题数据范围极小,可直接用最短路+DP水过。

  先预处理cost[i][j]表示从第i天到第j天都选择一样的路径的最小代价,直接用Dijkstra或SPFA即可。时间复杂度O(N2Mlog2M)或O(N2kE)。

  然后DP,f[i]表示从第1天到第i天的最小代价,边界f[0]=-K,转移方程f[i]=f[j]+cost[j+1][i]*(i-j)+K(j<i)。时间复杂度O(N2)。

  总时间复杂度O(N2Mlog2M)或O(N2kE)。

【参考代码】

  1 #include <cctype>  2 #include <cstdio>  3 #define REP(I,start,end) for(int I=(start);I<=(end);I++)  4 #define PER(I,start,end) for(int I=(start);I>=(end);I--)  5 #define maxint 32767  6 #define maxlongint 2147483647  7 typedef long long LL;  8 inline int getint()  9 { 10     char ch=getchar(); 11     for(;!isdigit(ch)&&ch!=-;ch=getchar()); 12     bool impositive=ch==-; 13     if(impositive) 14         ch=getchar(); 15     int result=0; 16     for(;isdigit(ch);ch=getchar()) 17         result=(result<<3)+(result<<1)+ch-0; 18     return impositive?-result:result; 19 } 20 inline LL getLL() 21 { 22     char ch=getchar(); 23     for(;!isdigit(ch)&&ch!=-;ch=getchar()); 24     bool impositive=ch==-; 25     if(impositive) 26         ch=getchar(); 27     LL result=0ll; 28     for(;isdigit(ch);ch=getchar()) 29         result=(result<<3)+(result<<1)+ch-0; 30     return impositive?-result:result; 31 } 32 template<typename T> inline bool getmax(T &target,T pattern) 33 { 34     return pattern>target?target=pattern,true:false; 35 } 36 template<typename T> inline bool getmin(T &target,T pattern) 37 { 38     return pattern<target?target=pattern,true:false; 39 } 40 //Header Template 41 #include <cstring> 42 using namespace std; 43 bool nownot[30],used[30],cannot[110][30]; 44 int n,rest[30],dist[30],f[110],map[30][30],cost[110][110]; 45 inline int Dijkstra() 46 { 47     int cnt=0; 48     REP(i,1,n) 49         if(!nownot[i]) 50             rest[++cnt]=i; 51     memset(dist,0x3f,sizeof(dist)); 52     memset(used,0,sizeof(used)); 53     dist[1]=0; 54     REP(i,2,cnt) 55     { 56         int miner=maxlongint,mini; 57         REP(j,1,cnt) 58             if(!used[j]&&getmin(miner,dist[j])) 59                 mini=j; 60         used[mini]=true; 61         REP(j,1,cnt) 62             if(!used[j]) 63                 getmin(dist[j],dist[mini]+map[rest[mini]][rest[j]]); 64     } 65     return dist[cnt]<dist[0]?dist[cnt]:-1; 66 } 67 int main() 68 { 69     int day=getint(); 70     n=getint(); 71     int K=getint(),m=getint(); 72     memset(map,0x3f,sizeof(map)); 73     while(m--) 74     { 75         int u=getint(),v=getint(),l=getint(); 76         map[u][v]=map[v][u]=l; 77     } 78     int d=getint(); 79     memset(cannot,0,sizeof(cannot)); 80     while(d--) 81     { 82         int p=getint(),start=getint(),end=getint(); 83         REP(i,start,end) 84             cannot[i][p]=true; 85     } 86     REP(i,1,day) 87     { 88         memset(nownot,0,sizeof(nownot)); 89         REP(j,i,day) 90         { 91             REP(k,1,n) 92                 nownot[k]|=cannot[j][k]; 93             cost[i][j]=Dijkstra(); 94         } 95     } 96     memset(f,0x7f,sizeof(f)); 97     f[0]=-K; 98     REP(i,1,day) 99         REP(j,0,i-1)100         {101             int c=cost[j+1][i];102             if(c>=0)103                 getmin(f[i],f[j]+cost[j+1][i]*(i-j)+K);104         }105     printf("%d\n",f[day]);106     return 0;107 }

 

bzoj1003题解