题意
这是一道交互题,有n个字符串,每个字符串长度:0-2000, n :0-2000
有一个机器对他进行排版,你可以给他一个每行的最大宽度w,那么每行只能放长度为w的字符;
每行相邻两个字符串之间至少有一个空格,每行结尾可以不用,机器会按照贪心原则进行排版,保证排版后的高度尽量小。
你可以进行n+30次询问,每次询问你可以给个w,他会给你排版后高度h,让你求出w*h的最小值。
做题吐槽
这题很典型的构造题,不会就是不会,会了一下子就会做了,这种题感觉就是要一下子找到题目的突破点,挖掘出这类题目的特征,感觉自己还是菜,每个突破点想到了,但是没串连起来,继续加油!
提示
1. 答案的范围变化是很小的,变化范围只有0-2000
2. 当 h= 1 的时候,很显然是最优的w是每个字符空一格
3. 当求出h = 1时候的答案h*w = s时,在h改变时,最多就是换行符号替换了空格,s变化为s-(h-1),并且需要整除h,那么只有一个点 s/h 满足
4. 这样就做出来了,先二分找出h=1时,w的最小值,对后续每个h高度询问一次检查一下就可得到最终解
反正很玄妙,如何想到变化范围小,如何想到整除,我感觉只能这种题只能从极值考虑,例如h=1,h=n这些点看看有没有什么特征,根据特征再去推理过程
代码
#include<bits/stdc++.h>
using namespace std;
void run() {
int n;
cin >> n;
int l = 2 * n - 1, r = n * 2000 + n, flag = -1;
while (l <= r) {
int mid = (l + r) >> 1;
int x;
cout << "? " << mid << endl;
cin >> x;
if (x == 1) {
flag = mid;
r = mid - 1;
} else {
l = mid + 1;
}
}
int s = flag;
// cout<<s<<endl;
int ans = s;
for (int i = 2; i <= n; i++) {
cout << "? " << s / i << endl;
int x;
cin >> x;
if (x)
ans = min(ans, x * (s / i));
}
cout << "! " << ans << endl;
}
int main() {
run();
return 0;
}
标签:exe,cout,int,notepad,Codeforces,2000,每行,flag,排版
From: https://www.cnblogs.com/4VDP/p/16830277.html