2012 ACM/ICPC Asia Regional Changchun Online 解题报告

来源:互联网 发布:java中的关键字 编辑:程序博客网 时间:2024/04/30 15:28

hdu 4276 The Ghost Blows Light

这个题是树形dp比赛的时候一直超时,囧,最后将代码进行了优化,然后就过了

我的思路是,先将1到n的边先走,将走过的边时间改为0,然后其他的边都得走二次!剩下的就是简单的tree dp了,当时的代码太乱了!以至于超时!

#include <iostream>#include <stdio.h>#include <algorithm>#include <string.h>using namespace std;#define N 110#define M 510int n,t;struct note{    int v,next,time;}edge[N*2];int dat[N],head[N],kk;void init(){    kk = 1;    memset(head,-1,sizeof(head));}void add(int fa,int son,int val){    edge[kk].time = val;    edge[kk].v = son;    edge[kk].next = head[fa];    head[fa] = kk++;}int temp;bool dfs(int rt,int fa){    if(rt == n) return 1;    for(int i = head[rt];i != -1;i = edge[i].next)    {        int son = edge[i].v;        if(son == fa) continue;        if( dfs(son,rt) )        {            temp += edge[i].time;            edge[i].time = 0;            return 1;        }    }    return 0;}int dp[N][M];//表示第i个点消耗M时间时的耗费int mma[N][M];void dfs2(int rt,int fa){    for(int i = head[rt];i != -1;i = edge[i].next)    {        int son = edge[i].v;        if(son == fa) continue;        dfs2(son,rt);         int cost = edge[i].time*2;        /**        第二层循环的j从大到小循环是因为cost肯能是0        这儿使用的是滚动数组计数,当cost=0时,dp[rt][i]就会使用本次的dp[rt][i];造成错误        从大到小循环,可以解决的问题是,最开始使用的dp[rt][i]必是上一次的,        且以后不会再用点dp[rt][i];        */        for(int i = t;i >= cost;i--)            for(int j = i-cost;j >= 0;j--)//这个顺序怎么会有问题???  //for(int j = 0;j <= i-cost;j++)                dp[rt][i] = max(dp[rt][i],dp[rt][j] + dp[son][i - cost - j]);    }    for(int i = 0;i <= t;i++)    dp[rt][i] += dat[rt];}int main(){    while(scanf("%d%d",&n,&t) != EOF)    {        init();        int a,b,v;        for(int i = 1;i < n;i++)        {            scanf("%d%d%d",&a,&b,&v);            add(a,b,v);            add(b,a,v);        }        for(int i = 1;i <= n;i++) scanf("%d",&dat[i]);        memset(dp,0,sizeof(dp));        temp = 0;        dfs(1,-1);        if(temp > t)        {            printf("Human beings die in pursuit of wealth, and birds die in pursuit of food!\n");            continue;        }        t-= temp;        dfs2(1,-1);        printf("%d\n",dp[1][t]);    }    return 0;}/*2 11 2 11 15 101 2 22 3 22 5 33 4 31 2 3 4 55 101 2 22 3 22 5 83 4 31 2 3 4 55 101 2 32 3 22 5 83 4 31 2 3 4 5*/

hdu 4277 USACO ORZ

这个题应该是离散化 dp 吧

重点工作是判重问题,我的方法是:将前i个数构成的三边中第一大的和第二大的作为判重的标准!

/**1011*/#include <iostream>#include <string.h>#include <stdio.h>#include <algorithm>#include <map>#include <utility>using namespace std;int dat[100];int sum;struct note{    int a,b,c;}re[1000000];bool cmp(const note a,const note b){    return a.a < b.a || (a.a == b.a && a.b < b.b) || (a.a == b.a && a.b == b.b && a.c < b.c);}int kk;void sort(int &a,int &b,int &c){    if(a > b) swap(a,b);    if(a > c) swap(a,c);    if(b > c) swap(b,c);}bool check(int a,int b){    int c = sum - a - b;    if(a+b > c && b + c > a && a+c > b)    {        //cout << a << " " << b << " " << c << "\n";        sort(a,b,c);        re[kk].a = a;        re[kk].b = b;        re[kk].c = c;        kk++;        return 1;    }    return 0;}pair<int,int> _make_pair(int _sum,int a,int b){    int c = _sum - a - b;    sort(b,a,c);    if(a > b) return make_pair(a,b);    return make_pair(b,a);}bool same(note a,note b){    return a.a == b.a && a.b == b.b && a.c == b.c;}int main(){    int sss = 1;    for(int i = 0;i < 15;i++) sss *= 3;    //cout << sss;    int t,n;    scanf("%d",&t);    while(t--)    {        map < pair<int ,int > , int > dp[16];        scanf("%d",&n);        for(int i = 0;i < n;i++) scanf("%d",&dat[i]);        sum = 0;        for(int i = 0;i < n;i++) sum += dat[i];        //pair pp(0,dat[0]);        dp[0] [ make_pair(dat[0],0) ] ++;        dp[0] [ make_pair(0,0) ] ++;        int _sum = dat[0];        for(int i = 1;i < n;i++)        {            _sum += dat[i];            map<pair<int,int>,int>::iterator it = dp[i-1].begin();            for(;it!=dp[i-1].end();++it)            {                pair <int,int> p = it->first;                dp[i][_make_pair(_sum,p.first+dat[i],p.second)]++;                dp[i][_make_pair(_sum,p.first,p.second+dat[i])]++;                dp[i][_make_pair(_sum,p.first,p.second)]++;            }        }        int ree = 0;        kk = 0;        map<pair<int,int>,int>::iterator it = dp[n-1].begin();        for(;it!=dp[n-1].end();++it)        {            pair <int,int> p = it->first;            check(p.first,p.second) ;        }        sort(re,re+kk,cmp);        if(kk == 0) ree = 0;        else        {            ree = 1;            for(int i = 1;i < kk;i++)            {                if( !same(re[i],re[i-1]) ) ree++;            }        }        cout << ree << "\n";    }    return 0;}