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~~

posted @ 2012-09-08 18:31 yejinru 阅读(...) 评论(...) 编辑 收藏