IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    牛客 1041D MobileService

    ReiAC\'s Blog发表于 2021-01-31 00:43:49
    love 0

    题目链接:Mobile Service

    这个题最简单的想法就是直接把三个人的位置直接都放进状态,然而这样子的话复杂度到了$O(N*L^3)$实在是难以接受的复杂度。

    我们发现,员工的位置只要知道两个没有去服务上一个p[i]的人,第三个人一定在p[i]位置,因此我们知道其复杂度变为了$O(N*L^2)$已经是可以接受的状态了

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    
    #include<bits/stdc++.h>
    //#include<bits/extc++.h>
    //#define int long long
    //#define int __int128
    #define ull unsigned long long
    #define mmst0(x) memset(x,0,sizeof(x))
    #define mmst3f(x) memset(x,0x3f,sizeof(x))
    #define pb(x) push_back(x)
    
    using namespace std;
    //using namespace __gnu_pbds;
    
    const int INF=0x3f3f3f3f,MOD=1e9+7;
    
    int read(){char c;int num,f=1;while(c=(char)getchar(),!isdigit(c))if(c=='-')f=-1;num=(int)(c-'0');while(c=(char)getchar(),isdigit(c))num=num*10+(int)(c-'0');return num*f;}
    //void prt(int x){if(x<0){putchar('-');x=-x;}if(x>9)prt(x/10);putchar((char)(x%10+'0'));} //警告,如非必须(如__int128),请不要使用快写
    
    int l,n,ans=INF;
    int p[1003]={3};//让p[0]作为起始点=3
    int c[203][203];
    int f[1003][203][203];
    
    void work()
    {
        scanf("%d%d",&l,&n);//l=read();n=read();
        for(int i=1;i<=l;i++)
            for(int j=1;j<=l;j++) scanf("%d",&c[i][j]);//c[i][j]=read();
        for(int i=1;i<=n;i++) scanf("%d",p+i);//p[i]=read();
        mmst3f(f); f[0][1][2]=0;
        for(int i=0;i<n;i++)//p[0]已知为3,因此从0开始往i+1转移,然后得到结果
        {
            for(int x=1;x<=l;x++)
            {
                for(int y=1;y<=l;y++)
                {
                    int z=p[i],nxt=p[i+1],now=f[i][x][y];
                    if(x==y || x==z || y==z) continue;
                    f[i+1][x][y]=min(f[i+1][x][y],now+c[z][nxt]);//让z去
                    f[i+1][z][y]=min(f[i+1][z][y],now+c[x][nxt]);//让x去
                    f[i+1][x][z]=min(f[i+1][x][z],now+c[y][nxt]);//让y去
                }
            }
        }
        for(int x=1;x<=l;x++) 
            for(int y=1;y<=l;y++) 
            {
                //if(x==y || x==p[n] || y==p[n]) continue; //ans初始值==INF所以可以不用这句话
                if(f[n][x][y]<ans) ans=f[n][x][y];
            }
        cout<<ans<<endl;
        return;
    }
    
    signed main()
    {
        //ios::sync_with_stdio(false);cin.tie(NULL);
        int T=1;//read();
        for(int Case=1;Case<=T;Case++)
        {
            //printf("Case #%d: ",Case);
            work();
        }
        return 0;
    }
    

    然后写完发现这样子的话就要去掉#define int long long

    那么这个其实是可以滚动数组缩内存的

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    
    for(int i=0;i<n;i++)//p[0]已知为3,因此从0开始往i+1转移,然后得到结果
    {
        for(int x=1;x<=l;x++)
        {
            for(int y=1;y<=l;y++)
            {
                int z=p[i],nxt=p[i+1],now=f[i&1][x][y];
                if(x!=nxt && y!=nxt) f[(i+1)&1][x][y]=min(f[(i+1)&1][x][y],now+c[z][nxt]);//让z去
                if(z!=nxt && y!=nxt) f[(i+1)&1][z][y]=min(f[(i+1)&1][z][y],now+c[x][nxt]);//让x去
                if(x!=nxt && z!=nxt) f[(i+1)&1][x][z]=min(f[(i+1)&1][x][z],now+c[y][nxt]);//让y去
                f[i&1][x][y]=0x3f3f3f3f;
            }
        }
    }
    


沪ICP备19023445号-2号
友情链接