JSOI2010 快递服务 【动态规划】

最初始的状态:dp[i][j][k][l], 表示现在正在进行第i个需求,三个司机分别在j, k, l这三个城市

i可以省,因为j,k,l中必须有一个等于i

状态就变成了:dp[i][j][k],表现有一个司机在第i个需求的城市,其他两个司机分别在j城市和k城市

i这一维还可以滚掉

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define gi get_int()
const int MAXN = 300;
int get_int()
{
  int x = 0, y = 1;
  char ch = getchar();
  while (!isdigit(ch) && ch != '-')
    ch = getchar();
  if (ch == '-')
    y = -1, ch = getchar();
  while (isdigit(ch))
    x = x * 10 + ch - '0', ch = getchar();
  return x * y;
}

int dis[MAXN][MAXN], num[1001], cnt;
int dp[2][MAXN][MAXN];

int main()
{
  int n = gi;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++)
      dis[i][j] = gi;
  }
  num[cnt++] = 2;
  while (std::cin >> num[cnt])
    cnt++;
  for (int i = 1; i < cnt; i++)
    num[i]--;
  int status = 0;
  memset(dp, 0x3f, sizeof(dp));
  dp[status][1][0] = 0;
  for (int i = 0; i < cnt - 1; i++) {
    status ^= 1;
    for (int j = 0; j < n; j++)
      for (int k = 0; k < n; k++)
        dp[status][j][k] = 0x3f3f3f3f;
    for (int j = 0; j < n; j++) 
      for (int k = 0; k < n; k++) {
        dp[status][j][k] = std::min(dp[status][j][k], dp[status ^ 1][j][k] + dis[num[i]][num[i + 1]]);
        dp[status][num[i]][k] = std::min(dp[status][num[i]][k], dp[status ^ 1][j][k] + dis[j][num[i + 1]]);
        dp[status][num[i]][j] = std::min(dp[status][num[i]][j], dp[status ^ 1][j][k] + dis[k][num[i + 1]]);
      }
  }
  int ans = 0x3f3f3f3f;
  for (int i = 0; i < n; i++)
    for (int j = 0; j < n; j++)
      ans = std::min(ans, dp[status][i][j]);
  std::cout << ans;

  return 0;
}
posted @ 2021-05-24 17:19  enisp  阅读(67)  评论(0)    收藏  举报