您的位置:首页 > 其它

[ZJOI2006]物流运输trans dp 最短路

2013-07-11 23:09 267 查看
我太弱了。

最先果断想状压m,从1到2^20-1dp,直接超时。郁闷了很久,确实不知道哪里还能优化,在网上找了哈题解才知道,有另外的状态表示方法。

先预处理cost[i][j] 表示从i天到j天一直存在的路径的最短路(cost[i][j]不一定存在)。然后按天dp:f[i]=min(f[j]+cost[j][i]*(i-j)+k,cost[1][i]*i),(0<j<i)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<ctime>
#define maxn 50020
using namespace std;
int n,m,daijia,e,d;
int may[300][300];
int tot=0;
int nex[maxn],fir[maxn],en[maxn],w[maxn];
inline void insert(int x,int y,int z){
nex[++tot]=fir[x];
fir[x]=tot;
en[tot]=y;
w[tot]=z;

nex[++tot]=fir[y];
fir[y]=tot;
en[tot]=x;
w[tot]=z;
}

int c[300];
int key[1048576];
int sf[1010][1001];

int cost[1001][1001];

bool check(int i,int j){
if ((i|j)>j)return false;
return true;
}

int sta[2000];
inline int spfa(int j){
int dist[300],view[300];
int head=0,tair=1;
for (int i=1;i<=m;i++)dist[i]=0x7fffffff;
memset(view,0,sizeof(view));
dist[1]=0;
sta[1]=1;
view[1]=1;
while (head<tair head="" view="" sta="" head="" 0="" for="" int="" k="fir[sta[head]];k;k=nex[k])" if="" check="" c="" en="" k="" j="" if="" dist="" en="" k="">dist[sta[head]]+w[k]){
dist[en[k]]=dist[sta[head]]+w[k];
if (view[en[k]]==0){
sta[++tair]=en[k];
view[en[k]]=1;
}
}
}
// printf("%d %d\n",j,dist[m]);
return dist[m];
}

int f[1001];

int main(){
// freopen("1003.in","r",stdin);
// freopen("1003.out","w",stdout);
scanf("%d%d%d%d",&n,&m,&daijia,&e);
for (int i=1;i<=e;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
insert(x,y,z);
}
scanf("%d",&d);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
may[i][j]=1;
for (int i=1;i<=d;i++){
int p,x,y;
scanf("%d%d%d",&p,&x,&y);
for (int j=x;j<=y;j++)
may[j][p]=0;
}

c[1]=1;
for (int i=2;i<=m+1;i++)
c[i]=c[i-1]*2;
memset(sf,0,sizeof(sf));
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
if (may[i][j])
sf[i][i]+=c[j];
for (int i=1;i<=n;i++)
cost[i][i]=spfa(sf[i][i]);

for (int k=1;k<=n-1;k++)
for (int i=1;i<=n-k;i++){
sf[i][i+k]=sf[i][i]&sf[i+1][i+k];
if (sf[i][i+k])
cost[i][i+k]=spfa(sf[i][i+k]);
}
memset(f,31,sizeof(f));
for (int i=1;i<=n;i++){
if (cost[1][i]!=0x7fffffff&&cost[1][i]!=0) f[i]=cost[1][i]*i;
for (int j=1;j<=i-1;j++)
if (cost[j+1][i]!=0x7fffffff)
if (f[i]>f[j]+cost[j+1][i]*(i-j)+daijia)
f[i]=f[j]+cost[j+1][i]*(i-j)+daijia;
}
// for (int i=1;i<=n;i++)printf("%d ",f[i]);printf("\n");
printf("%d",f
);
return 0;
}
</tair></ctime></cstring></cmath></algorithm></cstdio></iostream>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息