南航ACM1081_合并石子

/*  题目:南航acm1081 思路:此题类似于最优二叉树的解法,符合贪心规则,即每次从序列中选取    两个最小的值相加求和,并取代此两个值放入原先序列,由于要取两    个最小的元素,故可以将原始序列建小顶堆,通过两次取最小即可。    算法复杂度为O(nlgn)。 提交情况:wrong answer 1次,原因是在调整堆时没有考虑右孩子不存在的情况。 收获:要对问题进行充分分析,转化为已知的算法求解。 */ #include using namespace std; typedef unsigned long long ULLI; ULLI stones[10008]; void adjust(ULLI n, ULLI num) { ULLI root, lchild, rchild, min, temp, tag; while (n*2 <= num) { root = stones[n]; lchild = stones[n*2]; rchild = stones[n*2+1]; if (n*2+1 > num) { tag = 1; min = lchild; } else { tag = lchild < rchild ? 1 : 0; min = lchild < rchild ? lchild : rchild; } if (min < root) { if (tag) { temp = stones[n]; stones[n] = stones[2*n]; stones[2*n] = temp; n = 2*n; } else { temp = stones[n]; stones[n] = stones[2*n+1]; stones[2*n+1] = temp; n = 2*n+1; } } else { break; } } } void buildHeap(ULLI n) { ULLI i; for (i = n/2; i >= 1; i--) adjust(i, n); } int main() { ULLI num, i, total, temp, pre, next; memset(stones, 0, sizeof(ULLI)*10008); cin >> num; for (i = 1; i <= num; i++) cin >> stones[i]; if (num == 1) { cout << "0" << endl; return 0; } buildHeap(num); total = 0; for (i = 0; i < num - 1; i++) { pre = stones[1]; temp = stones[1]; stones[1] = stones[num-i]; stones[num-i] = temp; adjust(1,num-i-1); next = stones[1]; total += pre + next; stones[1] = pre + next; adjust(1,num-i-1); } cout << total <

你可能感兴趣的:(ACM)