C++代码 复制代码  收藏代码
  1. //  [题意]   
  2. //  n辆车按顺序安排在一个渡口的左边或右边,不超过渡口长度最多放多少辆   
  3. //  相当于n个物品按顺序尽量多地放在两个相同容量的背包里   
  4. //  如果放不下后面的就不放了,题目还要求输出要放的车都放哪边?记录路径即可   
  5. //  由于是按顺序放,所以第i辆车放的话,i前面的车必然已经放好了,不可能不放   
  6.   
  7. //  [解题方法]   
  8. //  dp[i][j]=1 表示左边车占了j长度时,可以放i辆车   
  9. //  设前i辆车总长度为sum[i],则:   
  10. //  对于dp[i][j]左边占了j长度,右边就必然占了sum[i]-j的长度了   
  11. //  dp[i][j]=0 表示这种状态不可行   
  12. //  设V为公路长度,w[i]为第i辆车的长度,状态转移如下:(0<=j<=V)   
  13. //  dp[i][j] = (j>=w[i]&&dp[i-1][j-w[i]]) || (sum[i]-j<=V&&dp[i-1][j])   
  14. //                        放左边                       放右边   
  15.   
  16. #include <iostream>   
  17. #include <string.h>   
  18. #include <stdio.h>   
  19. #include <stdlib.h>   
  20. #include <algorithm>   
  21. using namespace std;   
  22. #define LL long long   
  23. #define N 2005   
  24. #define M 10005   
  25. #define inf 0x3fffffff   
  26.   
  27. int dp[N][M], w[N], sum[N];   
  28. int pre[N][M], ans[N];   
  29.   
  30. int main()   
  31. {   
  32.     int t, i, j, k, V, n, vj;   
  33.     cin >> t;   
  34.     while (t--)   
  35.     {   
  36.         cin >> V;   
  37.         V *= 100;   
  38.         memset (dp, 0, sizeof(dp));   
  39.         dp[0][0] = 1;   
  40.         n = 0;   
  41.         sum[0] = 0;   
  42.         while(cin >> k, k)   
  43.         {   
  44.             ++n;   
  45.             w[n] = k;   
  46.             sum[n] = sum[n-1] + k;   
  47.         }   
  48.         vj = -1;   
  49.         for (i = 1; i <= n; i++)   
  50.         {   
  51.             for (j = 0; j <= V; j++)   
  52.             {   
  53.                 if (j >= w[i] && dp[i-1][j-w[i]]) {   
  54.                     k = i;   
  55.                     vj = j;   
  56.                     dp[i][j] = 1;   
  57.                     pre[i][j] = j-w[i];   
  58.                 } else if (sum[i]-j <= V && dp[i-1][j]) {   
  59.                     k = i;      //更新最大能放的车辆数   
  60.                     vj = j;   
  61.                     dp[i][j] = 1;   
  62.                     pre[i][j] = j;  //记录路径   
  63.                 }   
  64.             }   
  65.         }   
  66.         i = k;   
  67.         while (i--)   
  68.         {   
  69.             j = pre[i+1][vj];   
  70.             if (j == vj) ans[i] = 1;   
  71.             else ans[i] = 0;   
  72.             vj = j;   
  73.         }   
  74.         cout << k << endl;   
  75.         for (i = 0; i < k; i++)   
  76.         {   
  77.             if (ans[i]) puts ("starboard");   
  78.             else puts ("port");   
  79.         }   
  80.         if (t) puts("");   
  81.     }   
  82.     return 0;   
  83. }