您的位置:首页 > 其它

51Nod-1821-最优集合

2017-03-14 01:02 260 查看
ACM模版

描述



题解

这道题属于一道模拟问题吧,如果没有定义错模拟这个词的话。

看到讨论区中有一个 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  模拟