- 
Divide N elements into arbitrary groups, the score is determined by the way of division, and the problem is to maximize the score. 
- 
If there are two elements, just put them in the same group if the score is positive, and put them in different groups if the score is negative. - But when you add a third element, if this one’s connection to the other elements is strong, you’ll say, “I knew I should have put them in the same group.
- Is the DP to find the score for each k-1 grouping based on the score for each additional one?
- Is that an exponential order, since each grouping cannot be equated?
- Oh, N is the maximum 16? Maybe that’s all right.
- This way, the first element will be in one group, the next element can join it or become a new group in two ways, and the third element…
- Hmmm, it’s going to be hard to update this grouping of data structure.
 
 
 
- 
Reading the explanation, I found the opposite approach, “divide a given set into two”, I see. 
- 
Start with the whole set and compute back with [memory recursion - Score 0 if the given set has 1 element
- There is an option to not split a given set
- It doesn’t affect anything outside the given set, so just return the maximum score.
 
- 
Scores per group - Since any subset S is used once anyway, let’s compute and cache it for all subsets first!
- I think I could DP this calculation process itself.
- I didn’t have to do it, I had AC, so I didn’t become one.
 
 
Score calculation per group
- Double loop for elements of a given set python
def calcScore(S):
    debug("enter calcScore: S", S)
    x = S
    ret = 0
    i = 0
    while x:
        if x & 1:
            debug(": i", i)
            for j in range(i):
                if (S >> j) & 1:
                    debug(": i, j, M[i,j]", i, j, M[i, j])
                    ret += M[i, j]
        x //= 2
        i += 1
    debug("leave calcScore: ret", ret)
    return ret
groupScore = [calcScore(i) for i in range(1 << N)]
subset enumeration of the given set python
def solve(S):
    x = S
    while x > 0:
        print(f"{x:08b}")
        x = (x - 1) & S
:
>>> solve(14)
00001110
00001100
00001010
00001000
00000110
00000100
00000010
>>> solve(10)
00001010
00001000
00000010
When combined, it looks like this.
- It gives the correct answer to the sample case, but it’s going to TLE. I need to rewrite the messy cache a little more seriously. python
def solve(N, M):
    FULLBIT = (1 << N) - 1
    def calcScore(S):
        # debug("enter calcScore: S", S)
        x = S
        ret = 0
        i = 0
        while x:
            if x & 1:
                # debug(": i", i)
                for j in range(i):
                    if (S >> j) & 1:
                        # debug(": i, j, M[i,j]", i, j, M[i, j])
                        ret += M[i * N + j]
            x //= 2
            i += 1
        # debug("leave calcScore: ret", ret)
        return ret
    groupScore = [calcScore(i) for i in range(1 << N)]
    # debug(": groupScore", groupScore)
    from functools import lru_cache
    @lru_cache(maxsize=None)
    def sub(S):
        ret = groupScore[S]
        x = (S - 1) & S
        while x > 0:
            y = (~x) & S
            v = sub(x) + sub(y)
            if v > ret:
                ret = v
            x = (x - 1) & S
        return ret
    return sub(FULLBIT)
AC enough to rewrite the cache. python
    table = [None] * (1 << N)
    def sub(S):
        ret = table[S]
        if ret != None:
            return ret
        ret = groupScore[S]
        x = (S - 1) & S
        while x > 0:
            y = (~x) & S
            v = sub(x) + sub(y)
            if v > ret:
                ret = v
            x = (x - 1) & S
        table[S] = ret
        return ret
AC https://atcoder.jp/contests/dp/submissions/15101926
This page is auto-translated from [/nishio/DP U](https://scrapbox.io/nishio/DP U) using DeepL. If you looks something interesting but the auto-translated English is not good enough to understand it, feel free to let me know at @nishio_en. I’m very happy to spread my thought to non-Japanese readers.