Submission

Status:
P-PP-PP--P

Score: 60

User: NJTYTYTY

Problemset: ประลอง

Language: cpp

Time: 0.002 second

Submitted On: 2025-03-07 06:50:19

#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <climits>
#include <cmath>
using namespace std;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n;
    cin >> n;
    vector<int> a(n);
    int total = 0;
    for(int i = 0; i < n; i++){
        cin >> a[i];
        total += a[i];
    }
    
    // กำหนดจำนวนสมาชิกในทีมที่ 1
    int m = (n % 2 == 0) ? n/2 : (n-1)/2;
    
    // หาค่าสูงสุดของผลรวมบวกและต่ำสุดของผลรวมน้อย (สำหรับใช้ในการ shift ค่า sum)
    int sumPos = 0, sumNeg = 0;
    for(int i = 0; i < n; i++){
        if(a[i] >= 0)
            sumPos += a[i];
        else
            sumNeg += a[i];
    }
    int offset = -sumNeg; // ผลรวมจริง = index - offset
    int range = sumPos - sumNeg + 1; // พื้นที่ของผลรวมที่เป็นไปได้

    // dp[count][s] = สามารถเลือก count ตัวที่มีผลรวม = (s - offset) ได้หรือไม่
    vector<vector<bool>> dp(m+1, vector<bool>(range, false));
    // parent[count][s] เก็บค่า s ของ state ก่อนหน้า
    vector<vector<int>> parent(m+1, vector<int>(range, -1));
    // used[count][s] เก็บ index ของตัวเลขที่ถูกเลือกใน state นี้
    vector<vector<int>> used(m+1, vector<int>(range, -1));
    
    // เริ่มต้น: เลือก 0 ตัวแล้วผลรวม 0 (ซึ่งอยู่ที่ index offset)
    dp[0][offset] = true;
    
    // สำหรับแต่ละ element (ดำเนินการตามลำดับของ input)
    for(int i = 0; i < n; i++){
        // ทำการ update จากจำนวนที่เลือกในตอนนี้โดยย้อนกลับ (เพื่อไม่ให้ใช้ element ซ้ำใน iteration เดียวกัน)
        for(int count = m - 1; count >= 0; count--){
            for(int s = 0; s < range; s++){
                if(dp[count][s]){
                    int ns = s + a[i];
                    if(ns < 0 || ns >= range) continue;
                    if(!dp[count+1][ns]){
                        dp[count+1][ns] = true;
                        parent[count+1][ns] = s;
                        used[count+1][ns] = i;
                    }
                }
            }
        }
    }
    
    // ค้นหาผลรวม s (ใน state dp[m]) ที่ทำให้ |2*s - total| มีค่าน้อยที่สุด
    int bestSumIndex = -1;
    int bestDiff = INT_MAX;
    for(int s = 0; s < range; s++){
        if(dp[m][s]){
            int curSum = s - offset; // ผลรวมที่ได้
            int diff = abs(total - 2 * curSum);
            if(diff < bestDiff){
                bestDiff = diff;
                bestSumIndex = s;
            }
        }
    }
    
    // ถ้าไม่พบ (ควรจะพบเสมอ) ก็ออกจากโปรแกรม
    if(bestSumIndex == -1){
        cout << "No solution\n";
        return 0;
    }
    
    // สร้าง subset สำหรับทีมที่ 1 โดยย้อนกลับจาก dp (จะได้ index ในลำดับย้อนกลับ)
    vector<int> team1Indices;
    int curCount = m;
    int curS = bestSumIndex;
    while(curCount > 0){
        int idx = used[curCount][curS];
        team1Indices.push_back(idx);
        int prevS = parent[curCount][curS];
        curS = prevS;
        curCount--;
    }
    // เรียง index ของทีมที่ 1 ตามลำดับต้นฉบับ (เพิ่มขึ้น)
    sort(team1Indices.begin(), team1Indices.end());
    
    // สร้างทีมที่ 2 โดยเลือกสมาชิกที่ไม่อยู่ในทีมที่ 1
    vector<int> team2Indices;
    vector<bool> inTeam1(n, false);
    for (int idx : team1Indices)
        inTeam1[idx] = true;
    for(int i = 0; i < n; i++){
        if(!inTeam1[i])
            team2Indices.push_back(i);
    }
    
    // แสดงผล ทีมที่ 1
    for (int idx : team1Indices)
        cout << a[idx] << " ";
    cout << "\n";
    // แสดงผล ทีมที่ 2
    for (int idx : team2Indices)
        cout << a[idx] << " ";
    cout << "\n";
    
    return 0;
}