tyvj1061Mobile Service

题目:http://www.joyoi.cn/problem/tyvj-1061

dp。枚举三个人现在的位置。

1.重点:当前必有一人正处在查询点上!于是省掉一维。

2.转移方程枚举上一阶段的 j 和 k 的位置比较好想。

3.通过 j < k 的限制避免重复。

4.转移的时候对于条件的小小注意。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int l,n,q[1005],c[205][205],d[2][205][205],ans=2000005;
int main()
{
    scanf("%d%d",&l,&n);
    for(int i=1;i<=l;i++)
        for(int j=1;j<=l;j++)
            scanf("%d",&c[i][j]);
    memset(d[1],11,sizeof d[1]);
    scanf("%d",&q[1]);
    d[1][1][2]=c[3][q[1]];d[1][1][3]=c[2][q[1]];d[1][2][3]=c[1][q[1]];
    for(int i=2;i<=n;i++)
    {
//        printf("i=%d\n",i);
        memset(d[i%2],11,sizeof d[i%2]);
        scanf("%d",&q[i]);
        for(int j=1;j<l;j++)
            for(int k=j+1;k<=l;k++)
            {
                if(j==q[i-1]||k==q[i-1])continue;
                d[i%2][j][k]=min(d[i%2][j][k],d[(i-1)%2][j][k]+c[q[i-1]][q[i]]);
                if(q[i-1]==q[i])continue;
                int a=min(q[i-1],k),b=max(q[i-1],k);
                d[i%2][a][b]=min(d[i%2][a][b],d[(i-1)%2][j][k]+c[j][q[i]]);
                a=min(q[i-1],j);b=max(q[i-1],j);
                d[i%2][a][b]=min(d[i%2][a][b],d[(i-1)%2][j][k]+c[k][q[i]]);
            }
//        for(int j=1;j<l;j++)
//            for(int k=j+1;k<=l;k++)
//                printf(" q=%d j=%d k=%d d=%d\n",q[i],j,k,d[i][j][k]);
    }
    for(int i=1;i<l;i++)
        for(int j=i+1;j<=l;j++)
            ans=min(ans,d[n%2][i][j]);
    printf("%d",ans);
    return 0;
}

 

posted on 2018-03-14 00:33  Narh  阅读(163)  评论(0编辑  收藏  举报

导航