BZOJ 1003-DP+spfa
第一道AC的BZOJ的题目,从今天开始,我要狂刷BZOJ了,而且是一次AC好开心。
然而道路很坎坷,这道题在线下就一直过不了样例,问题多多。
链式前向星存图+spfa用来预处理cost[i][j],
dp就是非常简单的f[i]=min{f[j]+cost[j+1][i]*(i-j)+k},最后答案就是f[n]-k即可
dp的证明也比较容易,稍微思考一下就知道正确性啦。
然而,spfa预处理把我坑死了。spfa也是第一次写,还是很好写的,只要注意vis即出入队的标记即可,最短路算法基本都是初始化+松弛操作嘛。
前向星也没什么问题。但是这题有个约束,就在于有些码头有时候不能走,这个地方出问题了。目前解决方法是在每次求cost的也就是spfa前build一次,通过判断区间覆盖来确定这个点能不能走。然而本人蒟蒻,不仅这段程序写的弱,方法一定也很弱吧……
1 /************************* 2 Status :Accepted 3 DP+spfa 4 2015-09-25 5 *************************/ 6 #include <iostream> 7 #include <cstdio> 8 #include <cstring> 9 #include <string> 10 #include <algorithm> 11 #include <queue> 12 #include <vector> 13 using namespace std; 14 const int maxn =100+10; 15 const int maxm =20+5; 16 const int INF=1000000; 17 struct Edge{ 18 int to,next,w; 19 }e[maxm*maxm]; 20 int etot=0; 21 int head[maxm]; 22 void addEdge(int u,int v,int w){ 23 e[etot].w=w; 24 e[etot].to=v; 25 e[etot].next=head[u]; 26 head[u]=etot++; 27 } 28 struct unable{ 29 int p,st,ed; 30 unable(int p,int st,int ed):p(p),st(st),ed(ed){} 31 }; 32 vector<unable>un; 33 34 int cost[maxn][maxn]; 35 int n,m,k; 36 //spfa+buildG 37 queue<int>q; 38 bool vp[maxn]; //码头 39 bool vis[maxn]; 40 int d[maxm]; 41 void buildG(int x,int y){ 42 for(int i=1;i<=m;i++)vp[i]=true; 43 for(int i=0;i<un.size();i++){ 44 if(un[i].ed<x||un[i].st>y)continue; 45 vp[un[i].p]=false; 46 } 47 } 48 int spfa(int x,int y){ 49 buildG(x,y); 50 51 for(int i=1;i<=m;i++)d[i]=INF; 52 d[1]=0; 53 memset(vis,0,sizeof(vis)); 54 vis[1]=true; 55 q.push(1); 56 while(!q.empty()){ 57 int u=q.front();q.pop();vis[u]=false; 58 for(int i=head[u];i!=-1;i=e[i].next){ 59 int v=e[i].to,w=e[i].w; 60 // 61 //cout<<"VIS? "<<u<<' '<<v<<' '<<vp[v]<<!vp[v]<<endl; 62 // 63 if(!vp[v])continue; 64 // 65 //cout<<u<<' '<<v<<endl; 66 // 67 if(d[u]+w<d[v]){ 68 d[v]=d[u]+w; 69 if(!vis[v]){ 70 vis[v]=true; 71 q.push(v); 72 } 73 } 74 } 75 } 76 // 77 //if(x==y&&x==1){ 78 // for(int i=1;i<=m;i++)if(vp[i])cout<<i<<' '; 79 // cout<<endl; 80 // cout<<d[m]<<endl; 81 //} 82 // 83 return d[m]; 84 } 85 void read_in(){ 86 memset(head,-1,sizeof(head)); 87 int x; 88 cin>>n>>m>>k>>x; 89 for(int i=1;i<=x;i++){ 90 int a,b,w; 91 cin>>a>>b>>w; 92 addEdge(a,b,w); 93 addEdge(b,a,w); 94 } 95 cin>>x; 96 for(int i=1;i<=x;i++){ 97 int p,a,b; 98 cin>>p>>a>>b; 99 unable y(p,a,b); 100 un.push_back(y); 101 } 102 } 103 int f[maxn]; 104 void solve(){ 105 for(int i=1;i<=n;i++) 106 for(int j=i;j<=n;j++){ 107 cost[i][j]=spfa(i,j); 108 // 109 //if(cost[i][j]!=INF)cout<<i<<'~'<<j<<':'<<cost[i][j]<<endl; 110 // 111 } 112 113 for(int i=1;i<=n;i++)f[i]=INF; 114 f[0]=0; 115 for(int i=1;i<=n;i++) 116 for(int j=0;j<i;j++)f[i]=min(f[i],f[j]+cost[j+1][i]*(i-j)+k); 117 cout<<f[n]-k<<endl; 118 } 119 int main(){ 120 read_in(); 121 solve(); 122 return 0; 123 }
当有那么一天,你相信你可以做到的时候,那你就真的能够做到!
路在脚下