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 510
int 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 1
1 2 1
1 1
5 10
1 2 2
2 3 2
2 5 3
3 4 3
1 2 3 4 5
5 10
1 2 2
2 3 2
2 5 8
3 4 3
1 2 3 4 5
5 10
1 2 3
2 3 2
2 5 8
3 4 3
1 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;
}