• P4046 [JSOI2010]快递服务


    题目链接 双倍经验

    大致题意

    (m)个位置,从位置(p)移动到位置(q)需要花费(c(p,q))的价钱,但并不保证(c(p,q)≠c(q,p))

    现在有三个员工,初始位置在(1,2,3)和有(n)个请求,任何时刻只有一名员工可以移动,且不允许同一位置上有 (2) 个以上员工。第 (i) 个请求发生在位置 (p_i),公司必须按照顺序,派一名员工到位置 (p_i)去完成请求

    求公司的最小花费。

    分析

    (f(i,x,y,z))表示解决完前(i)个请求时,三个员工分别在(x,y,z)处时的最小花费,转移:

    (f(i+1,p_{i+1},y,z) = min{f(i,x,y,z)+c(x,p_{i+1})}qquad (p_{i+1}≠y≠z))

    (f(i+1,x,p_{i+1},z) = min{f(i,x,y,z)+c(y,p_{i+1})}qquad (x≠p_{i+1}≠z))

    (f(i+1,x,y,p_{i+1}) = min{f(i,x,y,z)+c(z,p_{i+1})}qquad (x≠y≠p_{i+1}))

    时空复杂度(O(nm^3)),无论是在时间上还是空间上都接受不了

    考虑优化:

    可以发现,在完成第(i)个任务时,一定有一个人站在(p_i)的位置上,也就是说,这个人的信息是"多余"的,只需要记录另外两个人的位置

    (f(i,x,y))表示解决前(i)个请求时,三个员工分别在(x,y,p_i)时的最小花费,转移:

    (f(i+1,p_i,y) = min{f(i,x,y)+c(x,p_{i+1})}qquad (p_i≠y≠p_{i+1}))

    (f(i+1,x,y) = min{f(i,x,y)+c(p_i,p_{i+1})}qquad (x≠y≠p_{i+1}))

    (f(i+1,x,p_i) = min{f(i,x,y)+c(y,p_{i+1})}qquad (x≠p_i≠p_{i+1}))

    时间复杂度(O(nm^2)),再用滚动数组优化一下空间即可

    (code)

    /*
    xcxc82
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define inf 1e9+10
    const int MAXN = 210;
    int T,L,n;
    inline int read(){
    	int X=0; bool flag=1; char ch=getchar();
    	while(ch<'0'||ch>'9') {if(ch=='-') flag=0; ch=getchar();}
    	while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+ch-'0'; ch=getchar();}
    	if(flag) return X;return ~(X-1);
    }
    int f[2][MAXN][MAXN];
    int val[MAXN][MAXN],a[MAXN*5];
    int main(){
    		memset(f,0x3f,sizeof(f));
    		L = read();
    		for(int i=1;i<=L;i++){
    			for(int j=1;j<=L;j++){
    				val[i][j] = read();
    			}
    		}
    	    a[0] = 3;
    		f[0][1][2] = 0;
    		int now;
    		while(cin>>now) a[++n] = now;
    		for(int i=0;i<=n-1;i++){
    			memset(f[i+1&1],0x3f,sizeof(f[i+1&1]));
    			for(int x=1;x<=L;x++){
    				for(int y=1;y<=L;y++){
    					if(x==y||x==a[i]||y==a[i]) continue;
    					f[i+1&1][a[i]][y] = min(f[i+1&1][a[i]][y],f[i&1][x][y]+val[x][a[i+1]]);
    					f[i+1&1][x][y] = min(f[i+1&1][x][y],f[i&1][x][y]+val[a[i]][a[i+1]]);
    					f[i+1&1][x][a[i]] = min(f[i+1&1][x][a[i]],f[i&1][x][y]+val[y][a[i+1]]);
    				}
    			}
    		}
    		int ans = 0x3f3f3f3f;
    		
    		for(int i=1;i<=L;i++) 
    		 for(int j=1;j<=L;j++) 
    		  ans = min(ans,f[n&1][i][j]);
    		  
    		printf("%d",ans);
       return 0;
    }
    
    
    
    
    
    
    
  • 相关阅读:
    聊聊click延迟和点击穿透
    setAttribute的浏览器兼容性(转)
    浅谈JS中的高级函数
    跨域总结
    本地存储小结
    ubuntu下pip的安装和使用
    并发编程艺术-锁类型以及底层原理
    HTTP协议以及HTTP2.0/1.1/1.0区别
    Paxos
    jvm垃圾收集器总结jdk1.7
  • 原文地址:https://www.cnblogs.com/xcxc82/p/14300486.html
Copyright © 2020-2023  润新知