hdu 4277 区域赛 1011 USACO ORZ

题目:
给出n条边,每条边有一定的长度,现在要用所有的边围成三角形,问能够围成多少个不同的三角形(三边至少有一边不等)。

分析:
对三角形进行编号,A,B,C三边,所有的边必定在其中的一条上面,只要三进制压缩枚举每条边所在的位置即可,也可以直接
dfs枚举即可。
另外注意到第一根木棍肯定在三角形的一条边上,所以根据对称关系,可以直接把他放在a号边即可

View Code
#include <cstdio>

#include <cstring>

#include <set>

#include <algorithm>



using namespace std;



const int X = 16;



int a[X],n,ans,sum;

int b[5];

set<pair<int,int> > ma;



void dfs(int pos,int suma,int sumb,int sumc){

    if(pos==n){        //这个是判断是否符合条件的,对三边进行排序且判断能否组成三角形

        if(suma<sumb){

            b[0] = suma;

            b[1] = sumb;

        }

        else{

            b[0] = sumb;

            b[1] = suma;

        }

        if(b[0]>sumc)

            b[0] = sumc;



        if(b[1]<sumc)

            b[1] = sumc;

        b[2] = sum-b[0]-b[1];

        swap(b[2],b[1]);



        if(b[0]+b[1]<=b[2])

            return;

        if(b[2]-b[0]>=b[1])

            return;

        if(ma.find(make_pair(b[0],b[1])) != ma.end())

            return;

        ans ++;

        ma.insert(make_pair(b[0],b[1]));

        return;

    }

    dfs(pos+1,suma+a[pos],sumb,sumc);

    dfs(pos+1,suma,sumb+a[pos],sumc);

    dfs(pos+1,suma,sumb,sumc+a[pos]);

}



int main(){

    freopen("sum.in","r",stdin);

    int ncase;

    scanf("%d",&ncase);

    while(ncase--){

        ma.clear();

        sum = 0;

        scanf("%d",&n);

        for(int i=0;i<n;i++){

            scanf("%d",&a[i]);

            sum += a[i];

        }

        ans = 0;

        dfs(1,a[0],0,0);

        printf("%d\n",ans);

    }

    return 0;

}

关于刚刚区域赛1006那题

可能刚刚改动了数据,我的程序WA掉了==。对大家造成不便,不好意思- -,我已经删了该博文了。。。

更新:1006那题应该是题目的问题,比赛中我就是以该程序对了,但是昨天晚上就不对了,刚才我改动了一处地方i<6改为i<8就对了(或者直接删掉该条件的判断貌似也是对的),貌似是题目大意不清楚,sorry~~

你可能感兴趣的:(USACO)