bzoj1003(ZJOI2006)物流運輸
阿新 • • 發佈:2018-06-04
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<<20View Code)+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; }
結果並不是。主要是當前走這條路線不用切換的條件不是上一次能走這條路線,而是上一次走了這條路線。
然後去看了看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)物流運輸