题目的意思大概就是给一个长方体的长宽高,问他能不能用一个w*h的纸剪出来,就是说展开图的长宽能不能比给定的小.
题目给了11中展开图的拓扑结构,我觉得这个很关键,要是题目没有给这个我可能想不到那么全面,不过题目已经给了我就分析那11个图形,发现展开图的长宽大概分为三类
假设长宽高为a,b,c,具体是多少并不重要,重要的是类别,具体的数值我们枚举一下排列就可以覆盖所有情况.
- 一边为 a+c+a+c,就是最长有四个连续的展开图的那些情况
另一个边的情况有a+b+c,b+c+c,a+a+b三种.虽然具体数值没有意义,但是符号是有意义的.如果一个边是a+c+a+c这就意味着我们认为b是中间他们四个共同的边,那么b就不能出现两次.但是其他两个位置放置不同就会不一样. - 一边为a+b+c+a,就是最长有三个连续展开图的情况.另一个边可能为a+b+c,b+c+c,a+a+b,同样不可能出现b出现两次的情况
- 一边为a+b+c+a+a,另一边为b+c
然后我们枚举排列,判断每一个排列是否存在情况满足条件
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<climits>
#include<cctype>
#include<queue>
#include<set>using namespace std;typedef long long ll;
const int INF=0x3f3f3f3f;
const int MAXN=1e5+5;int a[10];
int w,h;bool deal()
{int x,y,z;int w1,h1,h11,h12,h13,w2,h2,h21,h22,w3,h3;for(int i=0;i<3;i++){x=a[i];for(int j=0;j<3;j++){if(j==i) continue;y=a[j];for(int k=0;k<3;k++){if(k==j || k==i) continue;z=a[k];w1=x+x+z+z; h11=y+z+z; h12=x+y+z; h13=x+x+y;h1=min(h11,h12); h1=min(h1,h13);if(w1<=w && h1<=h || w1<=h && h1<=w) return true;w2=x+y+z+x; h21=x+y+z; h22=y+y+z;h2=min(h21,h22);if(w2<=w && h2<=h || w2<=h && h2<=w) return true;w3=x+y+z+x+x; h3=y+z;if(w3<=w && h3<=h || w3<=h && h3<=w) return true;}}}return false;
}int main()
{while(~scanf("%d%d%d",&a[0],&a[1],&a[2])){scanf("%d%d",&w,&h);if(deal()){printf("Yes\n");}else{printf("No\n");}}return 0;
}