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 }

 

posted @ 2015-09-25 11:58  JimmyLin^_^  阅读(184)  评论(0编辑  收藏  举报