• CH 5102 Mobile Service(线性DP)


    CH 5102 Mobile Service



    $ solution: $

    这道题很容易想到DP,因为题目里已经说了要按顺序完成这些请求。所以我们可以线性DP,但是这一题的状态不是很好设,因为数据范围有点大,而且我们需要记录三个人的位置信息。但是我们可以发现完成一个请求时三个人中必然有一人在这个请求的位置,所以我们可以根据请求来判断其中一人的位置,这样我们就只需要记录其他两个人了。而复杂度似乎刚好够用。

    设 $ F[i][j][k] $ 表示已经处理完第 $ i $ 个请求,且另外两个人分别在 $ j $ 和 $ k $ 的的最小花费,然后我们可以用这个状态向后转移:

    if(j!=a[i+1]&&k!=a[i+1])f[i+1][j][k]=min(f[i+1][j][k],f[i][j][k]+d[a[i]][a[i+1]]);
    if(a[i]!=a[i+1]&&k!=a[i+1])f[i+1][a[i]][k]=min(f[i+1][a[i]][k],f[i][j][k]+d[j][a[i+1]]);
    if(a[i]!=a[i+1]&&j!=a[i+1])f[i+1][a[i]][j]=min(f[i+1][a[i]][j],f[i][j][k]+d[k][a[i+1]]);
    

    需要注意题目说了不能有两个人在同一个位置!



    $ code: $

    #include<iostream>
    #include<cstdio>
    #include<iomanip>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #include<ctime>
    #include<cmath>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    
    #define ll long long
    #define db double
    #define inf 0x7fffffff
    #define rg register int
    
    using namespace std;
    
    int m,n,ans;
    int a[1005];
    int d[205][205];
    int f[1003][203][203];
    
    inline int qr(){
    	register char ch; register bool sign=0; rg res=0;
    	while(!isdigit(ch=getchar())) if(ch=='-')sign=1;
    	while(isdigit(ch)) res=res*10+(ch^48),ch=getchar();
    	return sign?-res:res;
    }
    
    int main(){
    	//freopen(".in","r",stdin);
    	//freopen(".out","w",stdout);
    	m=qr(); n=qr(); a[0]=1;
    	for(rg i=1;i<=m;++i)
    		for(rg j=1;j<=m;++j)
    			d[i][j]=qr();
    	for(rg i=1;i<=n;++i) a[i]=qr();
    	for(rg i=0;i<=n;++i)
    		for(rg j=1;j<=m;++j)
    			for(rg k=1;k<=m;++k)
    				f[i][j][k]=1e7;
    	f[0][2][3]=0;
    	for(rg i=0;i<n;++i){
    		for(rg j=1;j<=m;++j){
    			for(rg k=1;k<=m;++k){
    				if(f[i][j][k]<1e7){
    					if(j!=a[i+1]&&k!=a[i+1])f[i+1][j][k]=min(f[i+1][j][k],f[i][j][k]+d[a[i]][a[i+1]]);
    					if(a[i]!=a[i+1]&&k!=a[i+1])f[i+1][a[i]][k]=min(f[i+1][a[i]][k],f[i][j][k]+d[j][a[i+1]]);
    					if(a[i]!=a[i+1]&&j!=a[i+1])f[i+1][a[i]][j]=min(f[i+1][a[i]][j],f[i][j][k]+d[k][a[i+1]]);
    				}
    			}
    		}
    	} ans=1e7;
    	for(rg i=1;i<=m;++i)
    		for(rg j=1;j<=m;++j)
    			ans=min(ans,f[n][i][j]);
    	printf("%d
    ",ans);
    	return 0;
    }
    
    
  • 相关阅读:
    使用 PIVOT 和 UNPIVOT 行转列 列转行 报表统计 函数
    HAVING 子句 (SQL Server Compact)
    浅谈C#抽象类和C#接口
    大型高并发高负载网站的系统架构
    瞬时响应:网站的高性能架构
    Python之Subprocess模块
    Python之JSON序列
    Saltstack生产案例之系统初始化
    Saltstack配置管理
    CentOS6.5安装配置PPTP
  • 原文地址:https://www.cnblogs.com/812-xiao-wen/p/11007705.html
Copyright © 2020-2023  润新知