UVa11997 K Smallest Sums 归并 + 优先队列

UVa11997 K Smallest Sums 归并 + 优先队列_第1张图片



朴素算法O(n ^ n)啊,这都能做,想了想,最后只要输出其中和的前k小的就行了,有很多计算是冗余的啊,想了想,每行排个序,然后只算前两列,还有2 ^ k个,取k个绰绰有余了,O(2 ^ n),还能骗点分……扇自己一巴掌,卧槽你以为做PAT呢,还能骗分,然而还是忍不住交了一发……


WA代码:


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

struct node {
	int psum;
	node() {}
	node(int psum) : psum(psum) {}
	bool operator < (const node &on) const {
		return this->psum > on.psum;
	}
};

int k, cnt;
int a[755][755];
priority_queue Q;

void dfs(int dep, int sum) {
	if (cnt == 1000000) {
		return;
	}
	if (dep == k) {
		Q.push(node(sum));
		cnt++;
		return;
	}
	dfs(dep + 1, sum + a[dep][0]);
	dfs(dep + 1, sum + a[dep][1]);
}

int main()
{
	while (~scanf("%d", &k)) {
		for (int i = 0; i < k; i++) {
			for (int j = 0; j < k; j++) {
				scanf("%d", &a[i][j]);
			}
			sort(a[i], a[i] + k);
		}
		while (!Q.empty()) Q.pop();
		cnt = 0;
		dfs(0, 0);
		int c = 0;
		while (!Q.empty()) {
			printf(c++ == 0 ? "%d" : " %d", Q.top());
			Q.pop();
			if (c == k) break;
		}
		puts("");
	}
	return 0;
}


没仔细想还有没有别的什么错误,不过这O(2 ^ k)的复杂度肯定是不行的……


其实我只想到了一个起点,没想到归并,一列一列往下合并,横向地去求而不是纵向的,不断地往最小堆里扔,每次取最小的再合并再扔,最后时间复杂度O(n²logn)


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

struct node {
	int a, b;
	node() {}
	node(int a, int b) : a(a), b(b) {}
	bool operator < (const node& on) const {
		return this->a > on.a;
	}
};

int A[755][755], C[755];
int n;
priority_queue Q;

void Merge(int *A, int *B, int *C) {
	while (!Q.empty()) Q.pop();
	for (int i = 0; i < n; i++) {
		Q.push(node(A[i] + B[0], 0));
	}
	for (int i = 0; i < n; i++) {
		node tn = Q.top(); Q.pop();
		int a = tn.a, b = tn.b;
		C[i] = a;
		if (b + 1 < n) Q.push(node(a - B[b] + B[b + 1], b + 1));
	}
}

int main()
{
	while (~scanf("%d", &n)) {
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				scanf("%d", &A[i][j]);
			}
			sort(A[i], A[i] + n);
		}
		memcpy(C, A[0], sizeof(A[0]));
		for (int i = 1; i < n; i++) {
			Merge(C, A[i], C);
		}
		printf("%d", C[0]);
		for (int i = 1; i < n; i++) {
			printf(" %d", C[i]);
		}
		puts("");
	}
	return 0;
}





你可能感兴趣的:(UVa,排序,优先队列,归并)