1. 程式人生 > >ACM----三角形(有n根棍子,棍子i的長度為ai。)

ACM----三角形(有n根棍子,棍子i的長度為ai。)

題目:

        有n根棍子,棍子i的長度為ai。想要從中選出三根棍子組成周長儘可能長的三角形。請輸出最大的周長,若無法組成三角形則輸出0。

限制條件

3 ≤ n ≤ 100

1 ≤ ai ≤ 10^6
輸入

n = 5

a = {2,3,4,5,10}

輸出

12(選擇3、4、5時)

輸入

n = 4

a = {4,5,10,20}

輸出

0(無論怎麼選都無法組成三角形)

解法:

         這是《挑戰程式設計競賽(第二版)》裡的一道題,書中說了一種解法O(n³),另外,還特意說明另有一種O(nlogn)的解法,留給讀者思考。下面是兩種解法。

         我們知道組成三角形的充要條件是:最長的邊小於其餘兩邊之和;不難想到,可以三重迴圈列舉所有的選擇方案,再判斷能否組成三角形,最後找出最大的周長即可。

         另一種方法是先把棍子進行排序,然後只比較相鄰的三個棍子,最後選擇最大的周長。這樣只需一次迴圈即可。剛開始有點不明白這種思路,後來仔細想想就明白了,那就說說我的想法,假如棍子已經升序排序了,有a <  b <  c  <  d,如果有a + b > c且a + b > d,程式中並沒有比較a + b 和 d ,那麼是否會漏掉這種情況導致錯誤呢,不會的,因為如果a + b > d的話,那麼b + c 也一定 大於 d,而a + b 又小於 b + c,所以a + b 和 d後面的數的比較是多餘的,這樣就只需比較相鄰的三個棍子即可。下面上程式碼。

頭一種解法O(n³):

#include<stdio.h>
int MAX(int a,int b)
{
	return a > b ? a : b;
}
int main()
{
	int a[10];
	int i,j,k,n;
	scanf("%d",&n);
	for(i = 0; i < n; i++){
		scanf("%d",&a[i]);
	}
	int ans = 0;	//答案
	//讓i < j < k 這樣棍子就不會被重複選取了 
	for(i = 0 ;i < n;i ++){
		for(j = i + 1;j < n;j ++){
			for(k = j + 1;k < n;k ++){
				int l = a[i] + a[j] + a[k];	//周長 
				int max = MAX(a[i],MAX(a[j],a[k]));	//找出最長的棍子 
				int rest = l - max;	//其餘兩根棍子的長度之和 
				//如果可以構成三角形,則更新最大周長 
				if(rest > max){
					ans = MAX(ans,l);
				}
			}
		}
	}
	printf("%d\n",ans);
	return 0;
}


第二種解法O(nlogn):

#include<stdio.h>
int MAX(int a,int b)
{
	return a > b ? a : b;
}
int main()
{
	int a[10];
	int i,j,t,n;
	scanf("%d",&n);
	for(i = 0; i < n; i++){
		scanf("%d",&a[i]);
	}
	//氣泡排序(升序) 
	for(i = 0 ;i < n - 1;i ++){
		for(j = 0;j < n- i -1;j ++){
			if(a[j] > a[j + 1]){
				t = a[j];
				a[j] = a[j + 1];
				a[j + 1] = t;
			}
		}
	}
	int ans = 0;	//答案
	for(i = 0 ;i < n - 2;i ++){
		int l = a[i] + a[i + 1] + a[i + 2];	//周長 
		//如果可以構成三角形,則更新最大周長 
		if(a[i] + a[i + 1] > a[i + 2]){
			ans = MAX(ans,l);
		}
	}
	printf("%d\n",ans);
	return 0;
}

相關推薦

ACM----三角形(n棍子棍子i長度ai)

題目:         有n根棍子,棍子i的長度為ai。想要從中選出三根棍子組成周長儘可能長的三角形。請輸出最大的周長,若無法組成三角形則輸出0。 限制條件 3 ≤ n ≤ 100 1 ≤ ai ≤ 10^6 輸入 n = 5 a = {2,3,4,5,10}

n長度不同的木棒隨意選取三湊一個合法的三角形求總拼湊方案的數量(2018騰訊軟體開發-後臺開發方向秋招補考試題第三題)

題目: 有n根長度不同的木棒,隨意選取三根湊一個合法的三角形,求總拼湊方案的數量。對於兩個方案,只要有一根木棒的長度不同,則視為不同拼湊方案。 輸入描述 第一行為正數t(0 <= t <= 10),表示測試用例數 接下來每兩行一個測試資料,第一行一個整數n

度度熊想去商場買一頂帽子商場裏N頂帽子有些帽子的價格可能相同度度熊想買一頂價格第三便宜的帽子問第三便宜的帽子價格是多少?

length dex 相同 多少 turn this javascrip brush 便宜 var data=[10,25,50,10,20,80,30,30,40,90]; function fun(arr,index){ var min=Math.

n級臺階每次爬1或者2級臺階用程序計算多少種爬法

stat cnblogs 計算 多少 bsp span 方法 每次 spa 1.遞歸的方法: private static int Max(int i) { if (i<=2) { return i; }

現有n堆球其中n是偶數i堆中 ai 個球現需要將其中 n / 2 堆中的球數全變成完 全平方數另外的 n / 2 全不完全平方數

bcd dba amp com http abc 一行 增加 完全平方數 【問題描述】現有n堆球,其中n是偶數,第i堆中有 ai 個球。現需要將其中 n / 2 堆中的球數全變成完全平方數,另外的 n / 2 全不為完全平方數。你每一次操作可以選擇任意一堆增加或拿走(前提不

n個整數使前面各數順序向後移m個位置最後m個數變成前面m個數寫一函式:實現以上功能在主函式中輸入n個數和輸出調整後的n個數

import java.util.Scanner; public class Main {     public static void main(String[] args){         Scanner sc = new Scann

n個整數指定位置m處插入g個值(用指標和函式)

#include <stdio.h> void main() {     void move(int *p,int *s,int n,int m,int g);  int a[30],b[20];     i

LeetCode 給定一個 N 叉樹找到其最大深度 最大深度是指從節點到最遠葉子節點的最長路徑上的節點總數

/* // Definition for a Node. class Node { public:     int val;     vector<Node*> children;     Node() {}  

Problem C: 指標:n個整數使其前面各數順序向後移m個位置最後m個數變成最前面m個數

#include<stdio.h> int move(int *x,int n,int m) { int t[255]; int i; //int *p;指標迴圈變數p for(i=0;i<n;i++) t[i]=x[i];

[Al]演算法:n級階梯每次走1步或2步最多多少種走法

@Filename : floor.c * @Author : Mr.Zhong * @Date : 2018-11-02 * @Description: n級階梯,每次走一步或2步,最多有多少種走法 * @Analysis :

Bellman-Ford算法——什麽要循環V-1次?圖n個點又不能回路所以最短路徑最多n-1邊又因為每次循環至少relax一邊所以最多n-1次就行了!

bold source 頂點 路由 偽代碼 font 端點 -a 自底向上 單源最短路徑 給定一個圖,和一個源頂點src,找到從src到其它所有所有頂點的最短路徑,圖中可能含有負權值的邊。 Dijksra的算法是一個貪婪算法,時間復雜度是O(VLogV)(使用最小堆)。但是

給定一個二維平面平面上 n 個點求最多多少個點在同一條直線上

需求:給定一個二維平面,平面上有 n 個點,求最多有多少個點在同一條直線上。 分析思路: 1、將所有點二維座標化,即定義出所有點的x,y座標值 2、遍歷出所有取出兩點的情況(不考慮先後順序),根據任意兩點都確定一條直線,直線引數為k斜率,b與y軸交點的縱座標(此時x=0),將他們放入一個

ACMNO.41C語言-數字調序 n個整數使前面各數順序向後移m個位置最後m個數變成前面m個數見圖寫一函式:實現以上功能在主函式中輸入n個數和輸出調整後的n個數

題目描述 有n個整數,使前面各數順序向後移m個位置,最後m個數變成前面m個數,見圖。 寫一函式:實現以上功能,在主函式中輸入n個數和輸出調整後的n個數。 輸入 輸入資料的個數n n個整數 移動的位置m 輸出 移動後的n個數 樣例輸入 10 1 2 3 4

(C/C++語言實現)度度熊想去商場買一頂帽子商場裡N頂帽子有些帽子的價格可能相同度度熊想買一頂價格第三便宜的帽子問第三便宜的帽子價格是多少?

[程式設計題] 買帽子時間限制:1秒空間限制:32768K度度熊想去商場買一頂帽子,商場裡有N頂帽子,有些帽子的價格可能相同。度度熊想買一頂價格第三便宜的帽子,問第三便宜的帽子價格是多少? 輸入描述:首先輸入一個正整數N(N <= 50),接下來輸入N個數表示每頂帽子的價格(價格均是

C++求解:平面上n個點問總共可以組成多少條直線

思路 對輸入的點,兩兩組合求取斜率,這樣可能會出現某一斜率對應多對點。然後對屬於同一斜率的多對點,當成一幅圖,求取連通分支個數。 這裡對對屬於同一斜率的多對點,當成一幅圖,求取連通分支個數解釋一下: 假設對於斜率k=1.0,有點對 (1,1) ,(2,2