blablabla
blablabla
balbalbal
直接说dp思路
订单数组 in;
由于空间问题,三个员工所在位置用x,y,和z=in[i]表示
往前dp,当一个状态被激活的时候,对应的bool型标记变成true,用int型标记空间不够。
开始激活dp[z=in[0]=3][x=1][y=2]]状态并附初值0;
当处理第i+1份订单时,若第i份订单的(z=in[i],x,y)状态被激活了,往前推i+1份订单的三种状态
dp[i+1][x][y]=min(dp[i+1][x][y],dp[i][x][y]+mapp[z][in[i+1]]);//z=in[i]出发到in[i+1];
dp[i+1][z][y]=min(dp[i+1][z][y],dp[i][x][y]+mapp[x][in[i+1]]);//x到in[i+1];这时在i+1状态x变成in[i+1],z代替x的位置
dp[i+1][x][z]=min(dp[i+1][x][z],dp[i][x][y]+mapp[y][in[i+1]]);//同上
同时激活这三种状态
dpp[i+1][x][y]=true;dpp[i+1][z][y]=true;dpp[i+1][x][z]=true;
最后在第n份订单中找最小值输出就行
ps:这里也多用了点空间,要是把这最后一点空间也卡掉那就没办法了。
C++ 代码
#include<bits/stdc++.h>
using namespace std;
const int L=205;
const int N=1005;
const int maxint=2140083647;
int dp[N][L][L];
bool dpp[N][L][L];
int in[N];
int mapp[L][L];
//dp 还可以前推
int main()
{
int l,n;
scanf("%d %d",&l,&n);
int i=1,j=1;
for(;i<=l;i++)
for(j=1;j<=l;j++)
scanf("%d",&mapp[i][j]);
for(int i=1;i<=n;i++)
scanf("%d",&in[i]);
in[0]=3;
for(int i=0;i<N;i++)
for(int x=0;x<L;x++)
for(int y=0;y<L;y++)
{
dp[i][x][y]=maxint;
dpp[i][x][y]=false;
}
dpp[0][1][2]=1;//dp[0][1][2]激活;
dp[0][1][2]=0;
for(int i=0;i<n;i++)
{
for(int x=1;x<=l;x++)
for(int y=1;y<=l;y++)
{
int z=in[i];
if(x==y||y==z||z==x) continue;
int t=in[i+1];
if(dpp[i][x][y]==true)
{
dpp[i+1][x][y]=true;dpp[i+1][z][y]=true;dpp[i+1][x][z]=true;
dp[i+1][x][y]=min(dp[i+1][x][y],dp[i][x][y]+mapp[z][in[i+1]]);
dp[i+1][z][y]=min(dp[i+1][z][y],dp[i][x][y]+mapp[x][in[i+1]]);
dp[i+1][x][z]=min(dp[i+1][x][z],dp[i][x][y]+mapp[y][in[i+1]]);
}
}
} int ans=maxint;
for(int x=1;x<=l;x++)
{
for(int y=1;y<=l;y++)
{
if(dpp[n][x][y])
ans=min(ans,dp[n][x][y]);
}
} printf("%d\n",ans);
}