雕刻时光

just do it……nothing impossible
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

PAT1018——最短路加DFS

Posted on 2013-09-26 10:43  huhuuu  阅读(1124)  评论(0编辑  收藏  举报

http://pat.zju.edu.cn/contests/pat-a-practise/1018

在杭州各个点,有很多自助自行车的点,最大容纳点为CMAX,但比较适合的情况是CMAX/2,

现在从起点到终点,在最短路的情况下,调整各个车站的自行车数量使之CMAX/2,问开始时要提供的自行车最少与最后剩余的自行车最少的路径

最短路+DFS

在DFS时加上一个剪枝 if(lenth>dis[first])return ;就可以通过所有点

#include<stdio.h>
#define MAX 0x3ffffff
int cmax,N,end,M;
int node[599];
int map[599][599];
int path[599];

int rpath[599];
int in,out,nowstep,rstep;

bool hash[599][599];
int shortlen;

int dis[505];
bool use[505];
int ok=0;


void dijk( )
{
    int n=N,m;
    int min,rj,i,j;
    for(j=0;j<=n;j++)
    {
        dis[j]=map[0][j];
        use[j]=0;
    }
    use[0]=1;
    for(i=0;i<n;i++)
    {
        min=MAX;
        for(j=0;j<=n;j++)
        {
            if(use[j]==1)continue;
            if(dis[j]<min)
            {
                min=dis[j];
                rj=j;
            }
        }
        
        use[rj]=1;
        for(j=0;j<=n;j++)
        {
            if(use[j]==1)continue;
            if(dis[j]>dis[rj]+map[rj][j])
                dis[j]=dis[rj]+map[rj][j];
        }
    }

    shortlen=dis[end];
}


void print(){
    int i;
    printf("%d",in);
    printf(" 0");
    for(i=1;i<=rstep;i++){
        printf("->%d",rpath[i]);
    }
    printf(" %d\n",out);
}

void cal(){
    int tin=99999999,tout=999999999;
    int i,add=0;
    for(i=1;i<=nowstep;i++){
        add+=node[path[i]]-cmax/2;
        if(add<tin)tin=add;
    }
    if(tin>0)tin=0;
    else tin=-tin;
    tout=add+tin;

    if((tin<in)||((tin==in)&&tout<out)){
        in=tin;
        out=tout;
        if(in==0&&tout==0)ok=1;
        rstep=nowstep;
        for(i=1;i<=nowstep;i++){
            rpath[i]=path[i];
        }
    }

    //test
    /*
    printf("%d",tin);
    printf(" 0");
    for(i=1;i<=nowstep;i++){
        printf("->%d",path[i]);
    }
    printf(" %d\n",tout);
    */
}
void dfs(int step,int first,int lenth)
{
    if(ok==1||lenth>dis[first])return ; //lenth>dis[first] 是个关键的剪枝,不加的话最后一个点会超时
    if(lenth==shortlen&&first==end){
        nowstep=step;
        cal();
    }

    int j;
    for(j=1;j<=N;j++){
        if(hash[first][j]==1||map[j][first]==MAX)continue;
        hash[first][j]=hash[j][first]=1;
        path[step+1]=j;
        dfs(step+1,j,lenth+map[first][j]);
        hash[first][j]=hash[j][first]=0;
    }
}

int main()
{
    while(scanf("%d%d%d%d",&cmax,&N,&end,&M)!=EOF){
        int i,j,temp;
        ok=0;
        in=99999999;
        out=99999999;

        for(i=0;i<=N;i++){
            for(j=0;j<=N;j++){
                map[i][j]=MAX;
                hash[i][j]=0;
            }
        }

        for(i=1;i<=N;i++){
            scanf("%d",&node[i]);
        }
        

        int ll,rr,v;
        for(i=1;i<=M;i++){
            scanf("%d%d%d",&ll,&rr,&v);
            map[ll][rr]=map[rr][ll]=v;
        }
        dijk();
        dfs(0,0,0);
        print();
    }

    return 0;
}
View Code