#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
// 定义节点结构
typedef struct {
int level;
int sum;
} Node;
// 定义队列节点结构
typedef struct QueueNode {
Node data;
struct QueueNode *next;
} QueueNode;
// 定义队列结构
typedef struct {
QueueNode *front;
QueueNode *rear;
} Queue;
// 创建队列
Queue* createQueue() {
Queue *q = (Queue*)malloc(sizeof(Queue));
q->front = q->rear = NULL;
return q;
}
// 入队
void enqueue(Queue *q, Node item) {
QueueNode *newNode = (QueueNode*)malloc(sizeof(QueueNode));
newNode->data = item;
newNode->next = NULL;
if (q->rear == NULL) {
q->front = q->rear = newNode;
return;
}
q->rear->next = newNode;
q->rear = newNode;
}
// 出队
Node dequeue(Queue *q) {
if (q->front == NULL) {
Node nullNode = {0, 0};
return nullNode;
}
QueueNode *temp = q->front;
q->front = q->front->next;
if (q->front == NULL) {
q->rear = NULL;
}
Node item = temp->data;
free(temp);
return item;
}
// 判断队列是否为空
bool isEmpty(Queue *q) {
return q->front == NULL;
}
// 检查是否可以分割为两个和相等的子集
bool canPartition(int* nums, int numsSize) {
int sum = 0;
for (int i = 0; i < numsSize; i++) {
sum += nums[i];
}
if (sum % 2 != 0) {
return false;
}
int target = sum / 2;
Queue *q = createQueue();
Node start = {0, 0};
enqueue(q, start);
while (!isEmpty(q)) {
Node current = dequeue(q);
if (current.sum == target) {
return true;
}
if (current.level == numsSize) {
continue;
}
Node include = {current.level + 1, current.sum + nums[current.level]};
Node exclude = {current.level + 1, current.sum};
enqueue(q, include);
enqueue(q, exclude);
}
return false;
}
int main() {
int nums[200];
int n = 0;
while (scanf("%d", &nums[n]) != EOF) {
n++;
}
if (canPartition(nums, n)) {
printf("true\n");
} else {
printf("false\n");
}
return 0;
}
-
定义节点结构:
Node
结构体包含当前层次和当前和。
-
定义队列结构:
QueueNode
结构体用于队列节点。Queue
结构体包含队列的前后指针。
-
队列操作:
createQueue
函数创建一个新的队列。enqueue
函数将节点加入队列。dequeue
函数从队列中取出节点。isEmpty
函数检查队列是否为空。
-
检查是否可以分割为两个和相等的子集:
- 计算数组元素的总和,如果总和是奇数则不能分割,直接返回
false
。 - 计算目标和
target
为总和的一半。 - 使用广度优先搜索策略,通过队列进行分支限界法搜索:
- 从队列中取出当前节点。
- 如果当前和等于目标和,则返回
true
。 - 生成包括当前元素和不包括当前元素的两个子节点,并将它们加入队列。
- 如果队列为空且未找到满足条件的子集,则返回
false
。
- 计算数组元素的总和,如果总和是奇数则不能分割,直接返回
-
主函数:
- 读取输入的数组。
- 调用
canPartition
函数检查是否可以分割为两个和相等的子集。 - 输出结果。