- // [题意]
- // n辆车按顺序安排在一个渡口的左边或右边,不超过渡口长度最多放多少辆
- // 相当于n个物品按顺序尽量多地放在两个相同容量的背包里
- // 如果放不下后面的就不放了,题目还要求输出要放的车都放哪边?记录路径即可
- // 由于是按顺序放,所以第i辆车放的话,i前面的车必然已经放好了,不可能不放
- // [解题方法]
- // dp[i][j]=1 表示左边车占了j长度时,可以放i辆车
- // 设前i辆车总长度为sum[i],则:
- // 对于dp[i][j]左边占了j长度,右边就必然占了sum[i]-j的长度了
- // dp[i][j]=0 表示这种状态不可行
- // 设V为公路长度,w[i]为第i辆车的长度,状态转移如下:(0<=j<=V)
- // dp[i][j] = (j>=w[i]&&dp[i-1][j-w[i]]) || (sum[i]-j<=V&&dp[i-1][j])
- // 放左边 放右边
- #include <iostream>
- #include <string.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <algorithm>
- using namespace std;
- #define LL long long
- #define N 2005
- #define M 10005
- #define inf 0x3fffffff
- int dp[N][M], w[N], sum[N];
- int pre[N][M], ans[N];
- int main()
- {
- int t, i, j, k, V, n, vj;
- cin >> t;
- while (t--)
- {
- cin >> V;
- V *= 100;
- memset (dp, 0, sizeof(dp));
- dp[0][0] = 1;
- n = 0;
- sum[0] = 0;
- while(cin >> k, k)
- {
- ++n;
- w[n] = k;
- sum[n] = sum[n-1] + k;
- }
- vj = -1;
- for (i = 1; i <= n; i++)
- {
- for (j = 0; j <= V; j++)
- {
- if (j >= w[i] && dp[i-1][j-w[i]]) {
- k = i;
- vj = j;
- dp[i][j] = 1;
- pre[i][j] = j-w[i];
- } else if (sum[i]-j <= V && dp[i-1][j]) {
- k = i; //更新最大能放的车辆数
- vj = j;
- dp[i][j] = 1;
- pre[i][j] = j; //记录路径
- }
- }
- }
- i = k;
- while (i--)
- {
- j = pre[i+1][vj];
- if (j == vj) ans[i] = 1;
- else ans[i] = 0;
- vj = j;
- }
- cout << k << endl;
- for (i = 0; i < k; i++)
- {
- if (ans[i]) puts ("starboard");
- else puts ("port");
- }
- if (t) puts("");
- }
- return 0;
- }
转载于:https://blog.51cto.com/ajiao13/1131251