CSU2149: 监考的CSU-ACMer

 

Description

CSU-ACM开始接比赛出题的任务了!言下之意CSU-ACMer也开始监考了~

某天有三名队员派出去作为比赛的裁判。

 

比赛区域的每个时刻某个地方有一个请求,其中一个裁判必须赶到那个地方去(那个地方没有其他裁判)。

为了简化问题做以下约束/假设:

1、某一时刻只有一个裁判能移动,且裁判可以假设速度无限大,即瞬移,且只会直接到达请求位置,不会中途经过其他位置。

2、被请求后,裁判才能移动。

3、不允许在同样的位置出现两个裁判。

且任意一个裁判从p移动到q,需要花费c(p,q)的代价。

这个函数没有必要对称,但是c(p,p)=0。

 

裁判们必须满足所有的请求。作为CSU-ACM的代表,这些行动的代价和当然要是要最小化才行的啦~

Input

含有多组数据,对于每组数据:

第一行有两个整数L,N(3<=L<=200,1<=n<=1000)。L是位置数,N是请求数。

每个位置从1到L编号。下面L行每行包含L个非负整数。

第I+1行的第j个数表示c(i,j),并且它小于2000。

最后一行包含N个数,是请求列表。一开始三个裁判分别在位置1,2,3。

Output

对于每组数据输出一行,每行一个数M,表示最小代价。

Sample Input

5 9
0 1 1 1 1
1 0 2 3 2
1 1 0 4 1
2 1 5 0 1
4 2 3 4 0 
4 2 4 1 5 4 3 2 1

Sample Output

5

一道dp题。

在应答第i个请求时,枚举上一次的状态,枚举前两个人的位置L,R,那么第三个人的位置K=第i-1次请求,且满足L!=R,L!=K,R!=K。记F[I][L][R]为处理到第i个请求,第一个人在L,第二个人在R的答案。     那么此F[I-1][L][R]状态可以转移到F[I][L][k],F[I][L][R],F[R][K]

#include <iostream>
#include <stdio.h>
#include <string>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <queue>
#include <vector>
using namespace std;
typedef long long LL;
const int INF=0x3f3f3f3f;
const int maxn=205;
const double eps=1e-8;
const double pi=acos(-1.0);
const int MOD=10056;
int T,n,m,l;
int ma[maxn][maxn];
int a[1005];
int f[1005][maxn][maxn];

int main()
{
    while(scanf("%d %d",&l,&n)!=EOF)
    {
        memset(f,INF,sizeof(f));
        for(int i=1;i<=l;i++)
            for(int j=1;j<=l;j++)
            scanf("%d",&ma[i][j]);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        f[0][1][2]=f[0][1][3]=0;
        f[0][1][3]=f[0][3][1]=0;
        f[0][2][3]=f[0][3][2]=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=l;j++)
            {
                for(int k=1;k<=l;k++)
                {
                    if(j!=k)
                    {
                        int t=a[i-1];
                        if(t==0)
                            t=6-j-k;
                        if(j==t||k==t)
                            continue;
                        else
                        {
                            f[i][j][k]=min(f[i][j][k],f[i-1][j][k]+ma[t][a[i]]);
                            f[i][j][t]=min(f[i][j][t],f[i-1][j][k]+ma[k][a[i]]);
                            f[i][k][t]=min(f[i][k][t],f[i-1][j][k]+ma[j][a[i]]);
                        }
                    }
                }
            }
        }
        int ans=INF;
        for(int i=1;i<=l;i++)
        {
            if(i!=a[n])
            {
                for(int j=1;j<=l;j++)
                {
                    if(i!=j&&j!=a[n])
                        ans=min(ans,f[n][i][j]);
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

/**********************************************************************
	Problem: 2149
	User: jk1601zr
	Language: C++
	Result: AC
	Time:536 ms
	Memory:167172 kb
**********************************************************************/

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值