bzoj 1003 物流运输 最短路+dp

【题意】:一共要运输n天物资,每天都要从1号码头运送到m号码头,给你e行,每行告诉你从a号码头到b号码头的花费(无向图)。再告诉你d行,表示p号码头,在第 [a,b] 天内不能经过。当你某一天和上一天的运输路线不同时,需要额外花费k。现在让你求这n天加起来最小的总花费。

n<=20, m<=100

【题解】:dp[i]代表前 i 天的最小花费,那么dp[i] 一定是从某一个dp[j] 转移过来,并且[ j+1,i ]这些天里走的是同一条路。用c[a,b] 表示[a,b]天内走同一条路的最小花费。

那么可以得出dp方程: dp[i] = min(dp[j-1] + c[j,i])

c[ ][ ]只要先预先跑一遍最短路即可。

【代码】:

#include
using namespace std;
typedef long long ll;
int n,m,k,e,a,b,C;
ll c[25][25];
bool fre[25][105],vis[105];
ll cost[105][105];
ll inf=(1ll<<63)-1;
ll dp[105];
void dijkstra(int l,int r)
{
    for(int i=0;i<=100;i++) vis[i]=0;
    set >st;
    st.clear();
    int flag=0;
    st.insert(make_pair(0,1));
    while(!st.empty()){
        int x=st.begin()->second;
        ll f=st.begin()->first;
        st.erase(st.begin());
        if(vis[x]==1) continue;
        vis[x]=1;
        if(x==m){
            flag=1;
            cost[l][r]=f;
            break;
        }
        for(int i=0;i<=m;i++){
            if(vis[i]==0&&c[x][i]){
                int flag2=0;
                for(int j=l;j<=r;j++){
                    if(fre[i][j]==1){
                        flag2=1;
                        break;
                    }
                }
                if(flag2==0){
                    st.insert(make_pair(f+c[x][i],i));
                }
            }
        }
    }
    if(flag==0){
        cost[l][r]=inf;
    }
}
int main(void)
{

    scanf("%d%d%d%d",&n,&m,&k,&e);
    for(int i=0;i

 

你可能感兴趣的:(动态规划,最短路)