51Nod-1821-最优集合
2017-03-14 01:02
260 查看
ACM模版
看到讨论区中有一个 ID 为 zhenhao 的大牛,写了十分详细的题解,我也是看了人家的思路才写的代码,像这种模拟的问题,需要注意的就是思路一定要清晰,把情况考虑周全了,不然很容易错,我就是少考虑一种情况,一直错。繁琐的循环判断有机的组合在一起,最后达到 O(T*(M+N)) 的复杂度还不行,还需要进行剪枝,break 或者不 break 都不影响思路的正确性时一定要记好 break,否则会 TLE,还有需要用输入外挂哦。
这里我就直接借用一下上面所说的大牛的题解,毕竟写得足够详细,我又足够懒惰!
描述
题解
这道题属于一道模拟问题吧,如果没有定义错模拟这个词的话。看到讨论区中有一个 ID 为 zhenhao 的大牛,写了十分详细的题解,我也是看了人家的思路才写的代码,像这种模拟的问题,需要注意的就是思路一定要清晰,把情况考虑周全了,不然很容易错,我就是少考虑一种情况,一直错。繁琐的循环判断有机的组合在一起,最后达到 O(T*(M+N)) 的复杂度还不行,还需要进行剪枝,break 或者不 break 都不影响思路的正确性时一定要记好 break,否则会 TLE,还有需要用输入外挂哦。
这里我就直接借用一下上面所说的大牛的题解,毕竟写得足够详细,我又足够懒惰!
假设现在得到可以凑出[1,t],那么假设有一个数x加进去: if x<=t+1,那么这个数是可以插入使得可以凑出[1,t+x]; else能够凑出的部分还是[1,t]; 所以将集合的元素排序一次,模拟直到找不到上述过程的x即可求出最优值。 然后现在有一个集合B,可以向A添加k个元素,先看A能够得到最优值是t,然后在B中选一个x满足x<= t+1最大,然后增加A的最优值为t+x,继续在A中得到新的最优值t1,然后继续在B中找到一个x满足x<=t1+1最大,增加A的最优值为t1+x,上述过程做k次即可。 想要得到O(n)的复杂度完成上述过程,我的做法是维护一个栈,将找到的满足x<=t+1的x放入栈中知道不满足,那么取出栈顶元素就是最适合放进A的值。所以总的复杂度是O(T*(n+m))。
代码
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> using namespace std; const int MAXN = 1010; int m[MAXN]; int temp[MAXN], key[MAXN], tp; int s[MAXN][MAXN]; int sk[MAXN], top; // 栈 template <class T> inline bool scan_d(T &ret) { char c; ret = 0; while ((c = getchar()) < '0' || c > '9'); while (c >= '0' && c <= '9') { ret = ret * 10 + (c - '0'), c = getchar(); } return true; } int exc(int n, int m) { int res = 0; for (int i = 0; i < m; i++) { if (s [i] <= res + 1) { res += s [i]; } else { key = i; break; } } return res; } int main(int argc, const char * argv[]) { // freopen("/Users/zyj/Desktop/input.txt", "r", stdin); int n; scan_d(n); for (int i = 1; i <= n; i++) { scan_d(m[i]); for (int j = 0; j < m[i]; j++) { scan_d(s[i][j]); } sort(s[i], s[i] + m[i]); temp[i] = exc(i, m[i]); } int T; scan_d(T); int a, b, k; while (T--) { scan_d(a); scan_d(b); scan_d(k); top = 0; tp = temp[a]; int j = 0; for (int i = key[a]; i < m[a]; i++) { if (s[a][i] <= tp + 1) { tp += s[a][i]; } else { if (!k) { break; } int flag = 1; for (; j < m[b]; j++) { if (s[b][j] <= tp + 1) { sk[top++] = s[b][j]; } else { if (!top) { break; } tp += sk[--top]; k--; flag = 0; break; } } if (flag && k > 0 && top) { tp += sk[--top]; k--; } else if (flag) { break; } i--; } } while (k > 0 && top) { tp += sk[--top]; k--; } printf("%d\n", tp); } return 0; }
相关文章推荐
- 51NOD 1821 最优集合 [并查集]
- 51nod 1821 最优集合(想法+贪心+并查集)
- 51nod 1821 最优集合 (思维+并查集or栈)
- 51NOD 1821 最优集合 栈
- 51nod 1821 最优集合
- 51nod 1821 最优集合(贪心+并查集)
- 51nod 1821 最优集合 并查集 || 栈
- 51nod 1821 最优集合
- 51Nod - 1821:最优集合 (求第一个不能被表示为多个数的和的数)(不错的动脑题)
- 51NOD 1821 最优集合 【并查集】
- 1821 最优集合
- 最优配对问题(集合上的动态规划) —— 状压DP
- 51nod 1616 最小集合(数论)(枚举)
- 支持向量机SVM(一):支持向量机SVM的推倒:从logistic回归,到函数间隔,集合间隔,到寻找最优间隔分类器。
- 集合上的动态规划---最优配对问题
- 【51nod 算法马拉松19 C】 集合对
- 51nod 1551 集合交易
- 51nod 1616 最小集合(数论)(枚举)
- 最优集合
- 51Nod-1573-美丽的集合