HDU 4571Travel in time 最短路+01背包

来源:互联网 发布:自学计算机游戏编程 编辑:程序博客网 时间:2024/06/06 02:10

题意:一些点,之间有双向边,每个点可以获得一个si值,但是也要付出相应ci的代价,你可以只经过那个点但是不获得那个si值,每次获得的si值要满足,大于最近一次获得的si值,也可以说,获得si值的顺序是严格从小到大的。

做的时候,先要考虑构造dp的模型,dp[i][j]就是时间为i最近一次是获得sj的值,此时获取的si的总值。初始化考虑是否获得初始点S的si值,求答案时,考虑是否获得E的si值,其实就是一样的,考虑是否获得每个点的si值作为初始化,考虑最后一次为是否获得每个点的si值做为最终答案,也就是两个循环的事。

坑来了。坑在ci可能为0,也就是说,如果你直接背包同一个t的状态可能有的先背有的后背,不同背的顺序得到的答案就会前后不一致。那么就对si排序,保证顺序是按照si来的,这样不管先背后备,就是按照si背的,不会有错。

还有一个坑,紫书的floyed打印错了,导致直接wa的没想法。

大概就是这些要注意的了。


代码:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int INF = 301;int dp[333][111];int dis[111][111];int Ci[111],Si[111];struct Node{    int o;    bool operator < (const Node&rhs)const{        return Si[o]<Si[rhs.o];    }}mp[111];int main(){//    freopen("data.in","r",stdin);    int W,cas=1,ans,N,M,T,S,E,u,v,l;    scanf("%d",&W);    while(W--){        scanf("%d%d%d%d%d",&N,&M,&T,&S,&E);        for(int i=0;i<N;i++)            scanf("%d",&Ci[i]);        for(int i=0;i<N;i++)            scanf("%d",&Si[i]);        for(int i=0;i<N;i++)            mp[i].o = i;        sort(mp,mp+N);        for(int i=0;i<N;i++)            for(int j=0;j<N;j++){                dis[i][j]=INF;                if(i==j) dis[i][j] = 0;            }        while(M--){            scanf("%d%d%d",&u,&v,&l);            if(dis[u][v]>l){                dis[u][v] = l;                dis[v][u] = l;            }        }        for(int i=0;i<N;i++)            for(int j=0;j<N;j++)                for(int k=0;k<N;k++)                    if(dis[j][i]<=T && dis[i][k]<=T)                        dis[j][k] = min(dis[j][k],dis[j][i]+dis[i][k]);        memset(dp,-1,sizeof dp);        for(int i=0;i<N;i++)            if(Ci[i]+dis[S][i] <= T)                dp[Ci[i]+dis[S][i]][i] = Si[i];//        for(int i=0;i<=T;i++)//            for(int j=0;j<N;j++){//                int mj = mp[j].o;//                for(int k=0;k<N;k++){//                    int mk = mp[k].o;//                    if(i - dis[mk][mj] - Ci[mj] >= 0 && dp[i - dis[mk][mj] - Ci[mj]][mk]!=-1){//                        if(Si[mk] < Si[mj]){//                            if(dp[i][mj]==-1 || dp[i][mj] < dp[i - dis[mk][mj] - Ci[mj]][mk] + Si[mj]){//                                dp[i][mj] = dp[i - dis[mk][mj] - Ci[mj]][mk] + Si[mj];//                            }//                        }//                    }//                }//            }        for(int i=0;i<=T;i++)            for(int j=0;j<N;j++){                int mj = mp[j].o;                if(dp[i][mj] == -1) continue;                for(int k=0;k<N;k++){                    int mk = mp[k].o;                    if(Si[mj] < Si[mk] && i + dis[mj][mk] + Ci[mk] <= T){                        if(dp[i + dis[mj][mk] + Ci[mk]][mk]==-1 || dp[i + dis[mj][mk] + Ci[mk]][mk] < dp[i][mj] + Si[mk]){                            dp[i + dis[mj][mk] + Ci[mk]][mk] = dp[i][mj] + Si[mk];                        }                    }                }            }        ans=0;        for(int j=0;j<N;j++)            for(int i=0;i<=T-dis[j][E];i++)                ans = max(ans,dp[i][j]);        printf("Case #%d:\n",cas++);        printf("%d\n",ans);    }    return 0;}


0 0
原创粉丝点击