Codeforces 1672 E. notepad.exe
  Pl29TRtmDUpC 2023年11月01日 51 0

题意

这是一道交互题,有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;
}

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  jTMfQq5cr55P   2024年05月17日   44   0   0 算法与数据结构
  jTMfQq5cr55P   2024年05月17日   40   0   0 算法与数据结构
Pl29TRtmDUpC