题意是给出最对12条边你 问最大可组成三角形面积是多大 (可有多个三角形) 典型的状态压缩 (最多12条边)
思路:
先暴力枚举所有可能三角形的面积 然后再根据状态压缩来做 最多可组成n/3个三角形 对每个三角形都记录三边或(运算) 和面积 然后判断进行合并 (根据且运算) 就行了
#include#include #include #include using namespace std ; double dp [1 <<14 ]; double max (double a ,double b ) { return a >b ?a :b ; } struct node { int pp ; double area ; }cont [1 <<14 ]; int main() { int n ,i ,j ,k ; int num [15 ]; double S ; while(~scanf ("%d" ,&n ),n ) { for(i =1 ;i <=n ;i ++) scanf ("%d" ,&num [i ]); memset (dp ,0 ,sizeof(dp )); int t =0 ; S =0 ; for(i =1 ;i <=n ;i ++) for(j =i +1 ;j <=n ;j ++) { for(k =j +1 ;k <=n ;k ++) { if(num [i ]+num [j ]>num [k ]&&num [i ]+num [k ]>num [j ]&&num [j ]+num [k ]>num [i ]) { double p =1.0 *(num [i ]+num [j ]+num [k ])/2 ; t ++; double s =sqrt (p *(p -num [i ])*(p -num [j ])*(p -num [k ])); cont [t ].pp =(1 <<i )|(1 <<j )|(1 <<k ); dp [(1 <<i )|(1 <<j )|(1 <<k )]=cont [t ].area =s ; } } } for(i =1 ;i <(1 <<(n +1 ));i ++) { for(j =1 ;j <=t ;j ++) { if((i &cont [j ].pp )==0 ) { dp [i |cont [j ].pp ]=max (dp [i |cont [j ].pp ],dp [i ]+cont [j ].area ); if(dp [i |cont [j ].pp ]>S ) S =dp [i |cont [j ].pp ]; } } } printf ("%.2lf\n" ,S ); } return 0 ; }