折纸 folding
【问题描述】
在非常紧张的 NOIP 考试中,有人喜欢啃指甲,有人喜欢转铅笔,有人喜欢撕 纸条,……而小 x 喜欢迷折纸。
现有一个 W * H 的矩形纸张,监考老师想知道,小 x 至少要折多少次才能使 矩形纸张变成 w * h 的矩形纸张。
注意,每次的折痕都要平行于纸张的某一条边。
【输入格式】
第一行包括两个整数 W,H。
第二行包括两个整数 w,h。
【输出格式】
输出一个整数,表示至少需要折的次数。若无解,则输出-1。
【输入输出样例】
Input1 | Input2 | Input3 |
2 7 2 2 |
5 5 1 6 |
10 6 4 8 |
Output1 | Output2 | Output3 |
2 | -1 | 2 |
【数据说明】
对于 20% 的数据满足:W = w 且 H,h≤3。
对于 100% 的数据满足: 1 ≤ W,H,w,h ≤ 9 10 。
Solve
先从错误中得出正确结论
#include<bits/stdc++.h> using namespace std; int W,H,w,h; int func(double a,int b){ if(b>=a) return 0; if(b>=a/2.0) return 1; return func(a/2.0,b)+1; } int main(){ // freopen("folding.in","r",stdin); // freopen("folding.out","w",stdout); cin>>W>>H>>w>>h; //特判 //如果一个目标宽度比最大的还大,那就不可能 if(max(W,H)<max(w,h)) {cout<<"-1"; return 0;} cout<<min(func(W,w)+func(H,h),func(W,h)+func(H,w)); return 0; } //29808 20197 //1900 28433
思想
首先,想想有没有不可能折成的情况
如果一个目标宽度比最大的还大,那就不可能折成。输出"-1"。
接着,把四个输入数按Ww,Hh或者是Wh,Hw这样对应,
目的是模拟两种折叠方式,即是把W折成w,H折成h还是把W折成h,H折成w。
最后两种方式中取最小值即可。
cout<<min(func(W,w)+func(H,h),func(W,h)+func(H,w));
再来看函数
一个边界条件
if(b>=a) return 0;
如果当前的目标宽度(b)大于或等于当前宽度(a)//好像应该是等于吧?不会大于了
就不用再折了。返回0;
应该问题就在这里吧?
我们只考虑要排除了“一个目标宽度比最大的还大”这种情况
要让特判更全面
不妨让判断全在里面
再用返回值inf来判断可不可以折成。
My Std
#include<bits/stdc++.h> using namespace std; int W,H,w,h; int func(double a,int b){ if(b>a) return 0x3f3f3f;//这里把开始的一种情况拎出来了 if(b==a) return 0; if(b>=a/2.0) return 1; return func(a/2.0,b)+1; } int main(){ // freopen("folding.in","r",stdin); // freopen("folding.out","w",stdout); cin>>W>>H>>w>>h; if(max(W,H)<max(w,h)) {cout<<"-1"; return 0;} cout<<min(func(W,w)+func(H,h),func(W,h)+func(H,w)); return 0; } //这里是我开始错了的一种情况 //29808 20197 //1900 28433 //答案:5 //错误答案:4
OK!