1. 程式人生 > >bzoj1003(ZJOI2006)物流運輸

bzoj1003(ZJOI2006)物流運輸

http com pac 是把 target AC tar opened code

題目:https://www.lydsy.com/JudgeOnline/problem.php?id=1003

一開始撕逼地以為是撕逼題。貪心什麽的。

技術分享圖片
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define ll long long
using namespace std;
const int T=105,N=25;const ll INF=0x7fffffff;
int t,n,m,K,head[N],xnt,ky[T];
ll cd[(1<<20
)+5],qd,lm,dis[N],mn,ans; bool vis[N]; struct Edge{ int next,to;ll w; Edge(int n=0,int t=0,ll w=0):next(n),to(t),w(w) {} }edge[805]; void add(int x,int y,ll z) { edge[++xnt]=Edge(head[x],y,z);head[x]=xnt; edge[++xnt]=Edge(head[y],x,z);head[y]=xnt; } bool ck(int s,int i){return s&(1<<i);}
void dj(int s) { memset(dis,1,sizeof dis);dis[1]=0; priority_queue<pair<ll,int>,vector<pair<ll,int> >,greater<pair<ll,int> > > q; memset(vis,0,sizeof vis);q.push(make_pair(0,1)); while(q.size()) { int k=q.top().second;q.pop(); while
(vis[k]&&q.size())k=q.top().second,q.pop(); if(vis[k])break;vis[k]=1;if(k==n)break; for(int i=head[k],v;i;i=edge[i].next) if(!vis[v=edge[i].to]&&ck(s,v)&&dis[v]>dis[k]+edge[i].w) dis[v]=dis[k]+edge[i].w,q.push(make_pair(dis[v],v)); } cd[s]=dis[n]; } void init() { qd=((1<<1)|(1<<n));lm=(1<<(n+1));memset(cd,1,sizeof cd); for(int s=qd;s<lm;s++)dj(s); } int main() { scanf("%d%d%d%d",&t,&n,&K,&m);int x,y;ll z; while(m--) { scanf("%d%d%lld",&x,&y,&z); add(x,y,z); } init(); scanf("%d",&m);int p; while(m--) { scanf("%d%d%d",&p,&x,&y); for(int i=x;i<=y;i++)ky[i]|=(1<<p); } mn=INF; for(int i=1;i<=t;i++) { mn=INF; for(int s=qd;s<lm;s++) if((ky[i]&s)==0) mn=min(mn,(ky[i-1]&s)==0?cd[s]:cd[s]+K); ans+=mn; } printf("%lld",ans); return 0; }
View Code

結果並不是。主要是當前走這條路線不用切換的條件不是上一次能走這條路線,而是上一次走了這條路線。

然後去看了看TJ。啊,是區間dp呀。於是枚舉區間長度,如何如何。但還是不對。

又去看TJ了。發現不應該是把兩個區間dp值拼起來,而是前 j 個點的dp值+後面點的最短路值。或者至少記錄一下當前dp值走了哪條路線,不然可能出現多加的切換費用。

其實最後發現可能不是因為這個錯了。d j 的時候那個“ck(s,v)”,其實是“! ck(s,v)”。唉,不知道怎麽過樣例的。中間輸出竟然也沒看出來,真可怕。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define ll long long
using namespace std;
const int T=105,N=25;const ll INF=0x7fffffff;
int t,n,m,K,head[N],xnt,ky[T];
ll dis[N],dp[T];
bool vis[N];
struct Edge{
    int next,to;ll w;
    Edge(int n=0,int t=0,ll w=0):next(n),to(t),w(w) {}
}edge[805];
void add(int x,int y,ll z)
{
    edge[++xnt]=Edge(head[x],y,z);head[x]=xnt;
    edge[++xnt]=Edge(head[y],x,z);head[y]=xnt;
}
bool ck(int s,int i){return s&(1<<i);}
ll dj(int s)
{
    memset(dis,1,sizeof dis);dis[1]=0;
    priority_queue<pair<ll,int>,vector<pair<ll,int> >,greater<pair<ll,int> > > q;
    memset(vis,0,sizeof vis);q.push(make_pair(0,1));
    while(q.size())
    {
        int k=q.top().second;q.pop();
        while(vis[k]&&q.size())k=q.top().second,q.pop();
        if(vis[k])break;vis[k]=1;if(k==n)break;
        for(int i=head[k],v;i;i=edge[i].next)
            if(!vis[v=edge[i].to]&&!ck(s,v)&&dis[v]>dis[k]+edge[i].w)//
                dis[v]=dis[k]+edge[i].w,q.push(make_pair(dis[v],v));
    }
    return dis[n];
}
ll sy(int l,int r)
{
    int sm=0;for(int j=l;j<=r;j++)sm|=ky[j];
    return dj(sm)*(r-l+1);
}
int main()
{
    scanf("%d%d%d%d",&t,&n,&K,&m);int x,y;ll z;
    while(m--)
    {
        scanf("%d%d%lld",&x,&y,&z);
        add(x,y,z);
    }
    scanf("%d",&m);int p;
    while(m--)
    {
        scanf("%d%d%d",&p,&x,&y);
        for(int i=x;i<=y;i++)ky[i]|=(1<<p);
    }
    memset(dp,1,sizeof dp);dp[0]=0;
    for(int i=1;i<=t;i++)
    {
        for(int j=0;j<i;j++)
            dp[i]=min(dp[i],dp[j]+sy(j+1,i)+K);
    }
    printf("%lld",dp[t]-K);
    return 0;
}

bzoj1003(ZJOI2006)物流運輸