1. 程式人生 > >[BZOJ1800][Ahoi2009]fly 飛行棋 暴力枚舉

[BZOJ1800][Ahoi2009]fly 飛行棋 暴力枚舉

space div jpg clu nbsp 數學 code NPU solution

Description

給出圓周上的若幹個點,已知點與點之間的弧長,其值均為正整數,並依圓周順序排列。 請找出這些點中有沒有可以圍成矩形的,並希望在最短時間內找出所有不重復矩形。

Input

第一行為正整數N,表示點的個數,接下來N行分別為這N個點所分割的各個圓弧長度

Output

所構成不重復矩形的個數

Sample Input

8
1
2
2
3
1
1
3
3


Sample Output

3

HINT

N<= 20
技術分享圖片

Solution

第一反應,$n$這麽小,狀壓?

再結合圖看了一下,就是道水題...

做法:暴力枚舉

四重或者二重都行。我寫了個四重的

枚舉四個邊,然後回憶一下初中數學初二內容,一個矩形的判定條件是對邊相等,然後四個角是直角。(這裏不用判直角,只要對邊相等就行了)

所以枚舉$i,j,k,l$,左上、右上,右下,左下。

在這之前預處理一下每個點到其他點的距離(順時針)以及整個圓的周長

判定條件就是$a[ i ][ j ] == a[ k ][ l ]$且$a[ j ][ k ] == sum - a[ i ][ l ]$

#include <bits/stdc++.h>

using namespace std ;

int n ;
int a[ 50 ][ 50 ] ;

int main() {
    int sum = 0 ;
    scanf( "%d" , &n ) ;
    for( int i = 1
; i <= n ; i ++ ) { scanf( "%d" , &a[ i ][ i + 1 ] ) ; sum += a[ i ][ i + 1 ] ; } for( int i = 1 ; i <= n ; i ++ ) { for( int j = i + 1 ; j <= n ; j ++ ) { a[ i ][ j ] = a[ i ][ j - 1 ] + a[ j - 1 ][ j ] ; } } int ans = 0
; for( int i = 1 ; i <= n ; i ++ ) { for( int j = i + 1 ; j <= n ; j ++ ) { for( int k = j + 1 ; k <= n ; k ++ ) { for( int l = k + 1 ; l <= n ; l ++ ) { if( a[ i ][ j ] == a[ k ][ l ] && a[ j ][ k ] == sum - a[ i ][ l ] ) ans ++ ; } } } } printf( "%d\n" , ans ) ; }

[BZOJ1800][Ahoi2009]fly 飛行棋 暴力枚舉