Description
There are two machines A and B. There are n tasks, namely task 1, task 2, ..., task n. You must assign each task to one machine to process it. There are some facts you must know and comply with:
- You must assign each task to only one machine to process.
- At any time, a machine can process at most one task.
- Task i (0 < i < n) can be processed if and only if each task j (0 < j < i) has been processed or processing.
- If a task is processing on one machine, it cannot be interrupted.
You want to do finish all the tasks as soon as possible.
Input
There are multiple test cases. The first line of the input is an integer T (0 < T < 1000) indicating the number of test cases. Then T test cases follow. Each test case starts with an integer n (0 < n < 100). The ith line of the next n lines contains two integers tA, tB (0 < tA, tB < 100), giving the time to process the ith task by machine A and machine B.
Output
For each test case, output the earliest time when all the tasks have been processed.
Sample Input
4 1 1 2 2 1 2 2 1 2 1 2 90 95 3 1 3 1 3 1 3
Sample Output
1 1 90 3
Hints
- Test case 1: Let machine A process task 1.
- Test case 2: Let machine A process task 1 and at the same time let machine B process task 2.
- Test case 3: Let machine B process task 1 and at the same time let machine A process task 2.
- Test case 4: Let machine A process all the tasks.
- 对于第i块,第i块能放的位置一定要大于前i-1块中最大的起始位置。
- 同样要大于个机器中的较小值。
- 所以两边的差值不会大于100,因此按照差值dp,记录的是差值是i时最小的能放的位置是多少
- 差值分为左边正和右边正两种。然后最后统计最小值即可。
- 据说这种类型叫做双塔dp,然而并不了解。。
#include<cmath> #include<queue> #include<stack> #include<vector> #include<string> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<functional> using namespace std; typedef long long LL; const int maxn=1e2+10; int T,n,a[maxn],b[maxn]; int L[maxn][maxn],R[maxn][maxn]; int main() { scanf("%d",&T); while (T--) { scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d%d",&a[i],&b[i]); memset(L,-1,sizeof(L)); memset(R,-1,sizeof(R)); L[0][0]=0; for (int i=1;i<=n;i++) { for (int j=0;j<=100;j++) { if (L[i-1][j]!=-1) { if (L[i][a[i]]==-1||L[i][a[i]]>L[i-1][j]+j) L[i][a[i]]=L[i-1][j]+j; if (b[i]<=j) { if (L[i][j-b[i]]==-1||L[i][j-b[i]]>L[i-1][j]+b[i]) L[i][j-b[i]]=L[i-1][j]+b[i]; } else { if (R[i][b[i]-j]==-1||R[i][b[i]-j]>L[i-1][j]+j) R[i][b[i]-j]=L[i-1][j]+j; } } if (R[i-1][j]!=-1) { if (R[i][b[i]]==-1||R[i][b[i]]>R[i-1][j]+j) R[i][b[i]]=R[i-1][j]+j; if (a[i]<=j) { if (R[i][j-a[i]]==-1||R[i][j-a[i]]>R[i-1][j]+a[i]) R[i][j-a[i]]=R[i-1][j]+a[i]; } else { if (L[i][a[i]-j]==-1||L[i][a[i]-j]>R[i-1][j]+j) L[i][a[i]-j]=R[i-1][j]+j; } } } } int ans=0x7FFFFFFF; for (int i=0;i<=100;i++) { if (L[n][i]!=-1) ans=min(ans,L[n][i]+i); if (R[n][i]!=-1) ans=min(ans,R[n][i]+i); } printf("%d\n",ans); } return 0; }
温故而知新#include<map> #include<cmath> #include<queue> #include<vector> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define ms(x,y) memset(x,y,sizeof(x)) #define rep(i,j,k) for(int i=j;i<=k;i++) #define per(i,j,k) for(int i=j;i>=k;i--) #define loop(i,j,k) for (int i=j;i!=-1;i=k[i]) #define inone(x) scanf("%d",&x) #define intwo(x,y) scanf("%d%d",&x,&y) #define inthr(x,y,z) scanf("%d%d%d",&x,&y,&z) typedef long long LL; const int low(int x) { return x&-x; } const int INF = 0x7FFFFFFF; const int mod = 1e9 + 7; const int N = 1e2 + 10; const int M = 1e5 + 10; int T, n, a, b, f[N][2 * N]; int main() { for (inone(T); T--;) { inone(n); ms(f, 1); f[0][N] = 0; int ans = INF; rep(i, 0, n - 1) { intwo(a, b); for (int j = 0; j < N + N; j++) { if (f[i][j] > M) continue; if (j >= N) { f[i + 1][a + N] = min(f[i + 1][a + N], f[i][j] + a); f[i + 1][j - b] = min(f[i + 1][j - b], f[i][j] + max(0, b + N - j)); } else { f[i + 1][j + a] = min(f[i + 1][j + a], f[i][j] + max(0, j + a - N)); f[i + 1][N - b] = min(f[i + 1][N - b], f[i][j] + b); } } } for (int j = 0; j < N + N; j++) ans = min(ans, f[n][j]); printf("%d\n", ans); } return 0; }