[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>
最先果断想状压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>
相关文章推荐
- bzoj 1003 [ZJOI2006]物流运输trans 最短路+DP
- BZOJ 1003: [ZJOI2006]物流运输trans(最短路+dp)
- 【BZOJ】【P1003】【ZJOI2006】【物流运输trans】【题解】【最短路+DP】
- bzoj1003: [ZJOI2006]物流运输trans[最短路+DP]
- [ZJOI2006] 物流运输trans (最短路dijkstra+dp)
- 【BZOJ1003】[ZJOI2006]物流运输trans【最短路】【DP】
- 最短路+DP [ZJOI2006]物流运输
- BZOJ 1003: [ZJOI2006]物流运输trans SPFA+DP
- BZOJ 1003 [ZJOI2006]物流运输trans ★(Dijkstra + DP)
- [BZOJ1003]ZJOI2006 物流运输 |最短路|DP
- 1003: [ZJOI2006]物流运输 最短路+dp
- [SPFA预处理+DP]1003: [ZJOI2006]物流运输trans
- [bzoj 1003] [ZJOI2006]物流运输:最短路,DP
- [ZJOI2006]BZOJ 1003 物流运输 - 最短路 - dp
- [BZOJ1003][ZJOI2006]物流运输(最短路+DP)
- bzoj 1003 [ZJOI2006]物流运输(最短路spfa+dp)
- BZOJ 1003: [ZJOI2006]物流运输trans DP+SPFA
- BZOJ1003: [ZJOI2006]物流运输trans(DP)
- BZOJ 1003([ZJOI2006]物流运输trans-SPFA+DP)
- BZOJ 1003 [ZJOI2006]物流运输trans SPFA+DP