[BZOJ1800][Ahoi2009]fly 飞行棋 暴力枚举
Description
给出圆周上的若干个点,已知点与点之间的弧长,其值均为正整数,并依圆周顺序排列。 请找出这些点中有没有可以围成矩形的,并希望在最短时间内找出所有不重复矩形。
Input
第一行为正整数N,表示点的个数,接下来N行分别为这N个点所分割的各个圆弧长度
Output
所构成不重复矩形的个数
Sample Input
8
1
2
2
3
1
1
3
3
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 ) ; }