10377: squee_spoon and his Cube III
Time Limit: 2 Sec Memory Limit: 128 MBSubmit: 70 Solved: 22
[ Submit][ Status][ Web Board]
Description
Input
Output
Sample Input
4
3 4 2 2
Sample Output
4
HINT
In the sample, we can divide all competitors into 3 groups:(1)(2)(3,4)
- At the beginning, 1st, 2nd and 3rd competitor started.
- At the end of 2 second, 3rd competitor finished. 4th competitor started.
- At the end of 3 second, 1st competitor finished.
- At the end of 4 second, 2nd and 4th competitor finished. All 4 persons has finished.
So the minimum total time is 4 seconds.
Source
这次比赛刚开始感觉还不错,一直都是1A,除了第一次CE╮(╯▽╰)╭,水题还是比较熟练地,然后出了5个后就歇菜了,一直卡在那个行列式的那个水题之上,其实一开始的做法是对的,但是忘记了特判等于1的情况,然后又用DFS各种做,然后TLE,然后就没然后啦,,赛后交下第一次加个特判的代码就过啦,不甘心啊。。。。而且那个表达式求值的题目也是基础题,但是还是敲挫了好多次,,,╮(╯▽╰)╭,,,代码能力啊!!!
然后这题,,袁学长出的废题,就是DP啦,一直找不到状态以及方程,然后贪心一下交了,果然WA
这里将dp[i][j]看做第一组有i个和第二组有j个的情况(第三组可以通过前两组以及总数得出)是否存在,存在的话就赋值为1,整个dp是用来表示所有可能的情况,最后再扫一遍找最小值
总结:找出状态解一切(dp题比较难想,但是很多时候看下题解又感觉很容易)
AC代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n;
bool dp[1500][1500];
int a[55];
int main() {
while(scanf("%d", &n) != EOF) {
memset(dp, 0, sizeof(dp));
int tot = 0;
for(int i = 0; i < n; i++) {
scanf("%d", &a[i]);
tot += a[i];
}
int end = tot / 3 + 55;
dp[0][0] = 1;
for(int k = 0; k < n; k++) {
for(int i = end; i >= 0; i--) {
for(int j = end; j >= 0; j--) {
if(dp[i][j]) {
dp[i + a[k]][j] = 1;
dp[i][j + a[k]] = 1;
}
}
}
}
int ans = tot;
for(int i = 0; i <= end; i++) {
for(int j = 0; j <= end; j++) {
if(dp[i][j]) {
int tmp = max(i, j);
tmp = max(tmp, tot - i - j);
ans = min(tmp, ans);
}
}
}
printf("%d\n", ans);
}
return 0;
}