中级农民
- 积分
- 100
- 大米
- 颗
- 鳄梨
- 个
- 水井
- 尺
- 蓝莓
- 颗
- 萝卜
- 根
- 小米
- 粒
- 学分
- 个
- 注册时间
- 2019-9-28
- 最后登录
- 1970-1-1
|
不知道是不是和楼主知道的是一个题,之前参加的一个ACM校赛好像挺类似的。
最后求得是最大翻转box得数量
可以用状压DP+BFS求解
- def dfs(num, next, index, state, stateDP, ansDP):
- if num == 0:
- x = 0
- for e in state:
- x |= (1 << e)
- stateDP[index].append(x)
- ansDP[index].append(len(state))
- else:
- if next > n or next > num:
- return
- state.append(next)
- dfs(num-next, next+1, index, state, stateDP, ansDP)
- state.pop()
- dfs(num, next+1,index, state, stateDP, ansDP)
- n,m = map(int, input().split())
- T = 1
- while (n | m) != 0:
- nums = list(map(int, input().split()))
- #stateDP: 第i轮翻转时,所能到达第j种情况的状态
- #ansDP :第i轮翻转时,所能到达第j种情况时,正面朝上的box
- stateDP, ansDP = [[] for _ in range(n)], [[] for _ in range(n)]
- for i in range(m):
- dfs(nums[i], 1, i, [], stateDP, ansDP)
- visited = [0] * (1 << (n+1))
- stack = [(0,0,0)] # (i轮游戏, state, ans)
- res = 0
- while len(stack) > 0:
- curI, curState, curAns = stack.pop(0)
- if curI == m:
- continue
- for i in range(len(stateDP[curI])):
- if (curState & stateDP[curI][i]) != 0:
- continue
- newState = curState | stateDP[curI][i]
- if visited[newState] == 0: #如果当前box之前没有被翻开过,且新的状态未被访问
- visited[newState] = 1
- stack.append((curI+1,newState,curAns + ansDP[curI][i]))
- res = max(res, curAns + ansDP[curI][i])
- print("Game {}: {}".format(T, res))
- n, m = map(int, input().split())
- T += 1
复制代码 |
|