暴露智商的IQ题吖

智商

最近做的一道催眠题~
(_ _)( - . - )(~ O~)……( - . - )
智商测试…… 有 N 个木棍,每个木棍有一个长度 Ai,任务是找出能组成的三角形的最大面积 S 是多少。

Input 第 1 行:一个整数 N,表示有 N 个木棍。 第 2~N+1 行:每行一个整数 Ai,表示第 i 个木棍的长度。

Output 一行一个整数,最大面积 S*100 后向下取整
如果不能组成三角形则输出 -1。

对于 10%的数据:N <= 3 
对于 30%的数据:N <= 10 
对于 100%的数据:3 <= N <= 40 , Ai<=40 

已知三角形三边长度 a,b,c,可使用海伦公式计算面积:
在这里插入图片描述

p=(a+b+c)]/2

以下是心理路程ε=(´ο`*)))

首先~没有思路时就按照肉眼可见不用思考的线索进行实用的瞎捣鼓╭(╯^╰)╮
那么先做一个计算面积的函数方便之后调用
(^-^)V
根据公式可以很容易的做出♪(^ ∇^ * ):
double calc(int a,int b,int c)
{
double p=(a+b+c)/2.0;
return sqrt(p*(p-a)(p-b)(p-c));
}
因为要开根啊什么的就用double吧,精确一点
在接下来的运算中可以按照要求
S *100 后向下取整( * ^ ▽^ *)

头文件不能用万能时,把能想到的都写上方便以后用(个人懒习惯(*^▽ ^ *))
#include < iostream>
#include < cstdio>
#include < cctype>
#include < cstdlib>
#include < cmath>
#include < ctime>
#include < string>
#include < algorithm>
#include < queue>
using namespace std;

然后,打上一个框架~
这里回顾一下输入输出

Input 第 1 行:一个整数 N,表示有 N 个木棍。 第 2~N+1 行:每行一个整数 Ai,表示第 i 个木棍的长度。

Output 一行一个整数,最大面积 S*100 后向下取整如果不能组成三角形则输出 -1。

int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) {scanf("%d",&a[i]);}
printf("%d\n",res);
return 0;
}

接下来捋一捋思路( ^ o^ )/~
有 N 个木棍,每个木棍有一个长度 Ai,任务是找出能组成的三角形的最大面积 S 是多少。

“最大”划重点啊^ _ ^

找最大的话,要么是最优,要么是比出来的

鉴于最优通常很费脑子,那就先比一比试试吧︿( ̄︶ ̄)︿

既然要比,那就枚举吧,挨个枚举面积

由公式可得面积是由边长可得,那么以边长为条件枚举吧

怎么以边长为条件呢

啊,忽略了一个小条件w(゚Д゚)w

“ 如果不能组成三角形则输出 -1。”

那么,首先判定是否能组成一个三角形
用一个bool数组进行记载好了,是为true,否为false
(^-^)V

数组当然是越小越好,,,,,,,,,,,,,,,,,,,,,
而如果以边为条件,,,,,,,
似乎应该是三条边对应三维数组?

(⊙o⊙)…一看就要爆栈的样子

那么如何简化呢,去掉一条边的条件什么的(ノ`Д)ノ

(キ`゚Д゚´)!!可以用另外两条边来象征第三边啊

只要知道到周长C,
即可得a3=C-a1-a2;

那么周长无疑就是棍棍总长了,在记录每根棍棍长度时顺便记录就好了(^o ^)/~

申请一个全局变量total(这样会自动初始化为0吖)
真是懒人福利(。-ω-)zzz

for(int i=1;i<=n;i++) {scanf("%d",&a[i]);total+=a[i];}

顺便把数组也设置成全局变量好了(^ o^)/~
const int N=40+10;
bool f[NN][NN];

//f[a][b]表示能否构成一个边长为a,b,c的三角形(c=tot-a-b)

这时也能顺便完成枚举的版块了
int res=-1;
for(int i=0;i<=total;i++)
for(int j=0;j<=total;j++)
{
if(!f[i][j]) continue;
int k=total-i-j;
res=std::max(res,(int)(calc(i,j,k)*100));
}

输出也好啦~ printf("%d\n",res);

接下来是大头了ε=(´ο`*))):
论如何枚举找到可行的组合方式
这就需要灵感了╭(╯^╰)╮
在这个工程中真是很容易犯困的(ノ`Д)ノ
。。。

(最后还是听老师讲的(差点睡着(@_@)))

周长是一定的,以小棍棍作为线索
当这条边多一根小棍棍时,那条边就少一条小棍棍,三角形仍然成立吗?

原先:a、b、c 同时a+b>c
后来:a+小棍棍、b-小棍棍、c
此时a+小棍棍+b-小棍棍
仍然>c

同理就可以逆向使用了(^-^)V
if(j>=a[i] && f[j-a[i]][k]) f[j][k]=1;
if(k>=a[i] && f[j][k-a[i]]) f[j][k]=1;

枚举条件首先是小棍棍
for(int i=1;i<=n;i++)

然后是两条边

	for(int j=total;j>=0;j--)
	for(int k=total;k>=0;k--)

搞定O(∩_∩)O!

接下来理一理就是完整代码了~


```cpp

```cpp
#include <iostream>
#include <cstdio>
#include <cctype>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <string>
#include <algorithm>
#include <queue>
using namespace std;

const int N=40+10;

int n,a[N],total=0;
bool f[N*N][N*N];//f[a][b]表示能否构成一个边长为a,b,c的三角形(c=tot-a-b)

double calc(int a,int b,int c)//海伦公式
{
	double p=(a+b+c)/2.0;
	return sqrt(p*(p-a)*(p-b)*(p-c));
}

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++) {scanf("%d",&a[i]);total+=a[i];}
	f[0][0]=1;
	for(int i=1;i<=n;i++)//枚举找到可行的组合方式:i(枚举棍棍)
		for(int j=total;j>=0;j--)//j、k(对长度进行设置枚举) 
			for(int k=total;k>=0;k--)
			{
				if(j>=a[i] && f[j-a[i]][k]) f[j][k]=1;
				if(k>=a[i] && f[j][k-a[i]]) f[j][k]=1;
			}
	int res=-1;
	for(int i=0;i<=total;i++)
		for(int j=0;j<=total;j++)
		{
			if(!f[i][j]) continue;
			int k=total-i-j;
			res=std::max(res,(int)(calc(i,j,k)*100));
		}
	printf("%d\n",res);
	return 0;
}`

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值