码迷,mamicode.com
首页 > 其他好文 > 详细

Mobile Service

时间:2019-05-21 19:19:07      阅读:163      评论:0      收藏:0      [点我收藏+]

标签:free   getch   time   etc   ems   turn   getc   isp   完成   

Mobile Service

有一\(1\times L\)的网格,3个人初始在1,2,3,给出从每个位置i移到另一个位置j的费用\(c[i][j]\),并且保证两个人不在同一位置,再给出n个请求,第i个请求记做\(p_i\),要求有一个人到达位置\(p_i\),问按先后顺序完成这些请求的最小费用,\(3<=L<=200, 1<=N<=1000\)

显然要表现出这是第几个请求,且要知道3个人的位置才能转移,故设\(f[i][j][k][l]\)表示第i个请求,位置分别在j,k,l的最小费用,但是注意到\(p[i]\)已经表示了一个人的费用,故只要设\(f[i][j][k]\)表示第i个请求,有2个人在位置j,k的最小费用,于是我们有

\[f[i+1][j][k]=\max(f[i+1][j][k],f[i][j][k]+c[p[i]][p[i+1]])(p[i+1]!=j,k)\]

\[f[i+1][j][p[i]]=\max(f[i+1][j][p[i]],f[i][j][k]+c[k][p[i+1]])(p[i+1]!=p[i],j)\]

\[f[i+1][k][p[i]]=\max(f[i+1][j][p[i]],f[i][j][k]+c[j][p[i+1]])(p[i+1]!=p[i],k)\]

边界:\(f[0][1][2]=0,p[0]=3\),其余无限大

答案:\(\min_{i,j=1}^L f[n][i][j](i\neq j)\)

参考代码:

阶段实现

#include <iostream>
#include <cstdio>
#include <cstring>
#define il inline
#define ri register
#define intmax 0x7fffffff
using namespace std;
int c[201][201],dp[1001][201][201],
    p[1001];
il void read(int&);
template<class free>
il free Min(free,free);
int main(){
    int l,n;
    read(l),read(n),memset(dp,66,sizeof(dp));
    for(int i(1),j;i<=l;++i)
        for(j=1;j<=l;++j)read(c[i][j]);
    for(int i(1);i<=n;++i)read(p[i]);
    p[0]=3,dp[0][1][2]=0;
    for(int i(0),j,k;i<n;++i)
        for(j=1;j<=l;++j)
            for(k=1;k<=l;++k){
                if(j==k||j==p[i]||k==p[i])continue;
                if(p[i+1]!=j&&p[i+1]!=k)dp[i+1][j][k]=Min(dp[i+1][j][k],dp[i][j][k]+c[p[i]][p[i+1]]);
                if(p[i+1]!=j&&p[i+1]!=p[i])dp[i+1][j][p[i]]=Min(dp[i+1][j][p[i]],dp[i][j][k]+c[k][p[i+1]]);
                if(p[i+1]!=k&&p[i+1]!=p[i])dp[i+1][k][p[i]]=Min(dp[i+1][k][p[i]],dp[i][j][k]+c[j][p[i+1]]);
            }
    int ans(intmax);
    for(int i(1),j;i<=l;++i)
        for(j=1;j<=l;++j)ans=Min(ans,dp[n][i][j]);
    printf("%d",ans);
    return 0;
}
template<class free>
il free Min(free a,free b){
    return a<b?a:b;
}
il void read(int &x){
    x&=0;ri char c;while(c=getchar(),c<'0'||c>'9');
    while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
}

dfs实现(超了时,恳求优化)

#include <iostream>
#include <cstdio>
#include <cstring>
#define il inline
#define ri register
#define intmax 0x7fffffff
using namespace std;
int w[201][201],p[201],
    dp[1001][201][201],n;
void search(int,int,int);
il void read(int&);
int main(){
    int l;read(l),read(n);
    for(int i(1),j;i<=l;++i)
        for(j=1;j<=l;++j)read(w[i][j]);
    for(int i(1);i<=n;++i)read(p[i]);
    memset(dp,66,sizeof(dp));
    dp[0][1][2]=0,p[0]=3,search(0,1,2);
    int ans(intmax);
    for(int i(1),j;i<=l;++i)
        for(j=1;j<=l;++j)
            ans=ans>dp[n][i][j]?dp[n][i][j]:ans;
    printf("%d",ans);
    return 0;
}
void search(int a,int b,int c){
    if(a==n)return;int opt;
    if(p[a+1]!=b&&p[a+1]!=c)
        if((opt=dp[a][b][c]+w[p[a]][p[a+1]])<dp[a+1][b][c])
            dp[a+1][b][c]=opt,search(a+1,b,c);
    if(p[a+1]!=p[a]){
        if(p[a+1]!=b)
            if((opt=dp[a][b][c]+w[c][p[a+1]])<dp[a+1][b][p[a]])
                dp[a+1][b][p[a]]=opt,search(a+1,b,p[a]);
        if(p[a+1]!=c)
            if((opt=dp[a][b][c]+w[b][p[a+1]])<dp[a+1][c][p[a]])
                dp[a+1][c][p[a]]=opt,search(a+1,c,p[a]);
    }
}
il void read(int &x){
    x&=0;ri char c;while(c=getchar(),c<'0'||c>'9');
    while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
}

Mobile Service

标签:free   getch   time   etc   ems   turn   getc   isp   完成   

原文地址:https://www.cnblogs.com/a1b3c7d9/p/10901645.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!