题解倒水
Posted kcn999
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解倒水相关的知识,希望对你有一定的参考价值。
题目描述
一天,CC买了N个容量可以认为是无限大的瓶子,开始时每个瓶子里有1升水。接着~~CC发现瓶子实在太多了,于是他决定保留不超过K个瓶子。每次他选择两个当前含水量相同的瓶子,把一个瓶子的水全部倒进另一个里,然后把空瓶丢弃。(不能丢弃有水的瓶子)
显然在某些情况下CC无法达到目标,比如N=3,
K=1,因为你会发现,把任意一个瓶子倒到另一瓶子后,只剩下一个1升水的瓶子和一个2升水的瓶子,这两个瓶子无法再相互倒水了,因此超过了K。
此时CC可以重新买一些新的瓶子(新瓶子容量无限,开始时有1升水),以到达目标,例如再买一个新瓶子,那么就有2个1升水的瓶子,把它们倒在一起,就得到一个2升水的瓶子,这样再和之前的2升水的瓶子倒在一起,最后就只剩下一个4升水的瓶子了,满足条件。
现在CC想知道,最少需要买多少新瓶子才能达到目标呢?如果无论买多少个瓶子都无法满足条件,则输出-1。
驶入输出格式
输入格式
多组测试数据。
第一行:一个整数r,表示共有r组测试数据,1<=r<=10。
每组测试数据的格式是:
一行两个正整数, N, K (1<=N<=10^7,K <= 1000)。
输出格式
共r行,每行对应一组测试数据,一个非负整数,表示最少需要买多少新瓶子。
输入输出样例
输入样例
3
3 1
13 2
1000000 5
输出样例
1
3
15808
题解
可以看出此题不存在-1的情况。
其实可以用$n$的二进制形式来表示起始的瓶子拥有情况,DFS一遍所有添加情况即可。
#include <iostream> #define lowbit(x) ((x) & -(x)) using namespace std; int G; int n, k; int maxn; int ans; void DFS(int now, int lim, int cnt) { if(now > maxn) return; int tmp = now, tot = 0; while(tmp) { ++tot; tmp -= lowbit(tmp); } if(tot <= k) { ans = min(cnt, ans); return; } tmp = now; while(tmp) { if(lowbit(tmp) > lim) DFS(now + lowbit(tmp), lowbit(tmp), cnt + lowbit(tmp)); tmp -= lowbit(tmp); } return; } int main() { cin >> G; int tmp; while(G--) { cin >> n >> k; tmp = n; while(tmp != lowbit(tmp)) { tmp -= lowbit(tmp); } maxn = tmp << 1; ans = 1 << 30; DFS(n, 0, 0); cout << ans << " "; } return 0; }
以上是关于题解倒水的主要内容,如果未能解决你的问题,请参考以下文章