hdu 2415 Bribing FIPA(树形DP)
2012-03-07 21:37
351 查看
题意:给定N个国家,相互之间可能存在附属关系,现在想要贿赂m个国家,已知,贿赂一个国家,那么如果该国家拥有附属国,那么他的所有附属国都可以算作已经贿赂。
分析:按照国家之间的附属关系连边(有向),之后将森林转为一棵树,就变成了一棵树上的01背包了。
因为国家是用名字给出的,先用字典树给名字编号……
dp[i][j]表示第i个国家及其附属国中选j个国家的最小花费
之前一直过不了的题,现在居然1A了,主要是思路比较清晰
View Code
分析:按照国家之间的附属关系连边(有向),之后将森林转为一棵树,就变成了一棵树上的01背包了。
因为国家是用名字给出的,先用字典树给名字编号……
dp[i][j]表示第i个国家及其附属国中选j个国家的最小花费
之前一直过不了的题,现在居然1A了,主要是思路比较清晰
View Code
#include<iostream> #include<algorithm> #include<string.h> #include<string> #include<vector> using namespace std; const int N = 210; int n,num,m,dp ,w ,in ; char s[20110]; bool vis ; vector<int> g ; typedef struct node { int cnt; struct node *next[52]; }*tree,Trie; tree root; inline int GetNum(char *t){ tree p = root,newnode; for(int i = 0;i < strlen(t); ++i){ int u = t[i] - 'a'; if(u<0) u=t[i]-'A'+26; if(p->next[u]==NULL) { newnode=(tree)malloc(sizeof(Trie)); newnode->cnt=-1; for(int j=0;j<52;j++) newnode->next[j]=NULL; p->next[u]=newnode; p=newnode; } else p = p->next[u]; } if(p->cnt == -1) //该节点未出现过 p->cnt = num ++; return p->cnt; } void init() { root=(tree)malloc(sizeof(Trie)); root->cnt=-1; for(int j=0;j<52;j++) root->next[j]=NULL; num=1; memset(in,0,sizeof(in)); for(int i=0;i<=n;i++) g[i].clear(); for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) dp[i][j]=INT_MAX; } int dfs(int u) { int size=g[u].size(); dp[u][0]=0; int t=0; for(int i=0;i<size;i++) { int v=g[u][i]; int now=dfs(v); for(int j=t;j>=0;j--)//当前z树选择j个点 { for(int k=0;k<=now;k++)//以v为根的子树选择k个点 dp[u][j+k]=min(dp[u][j+k],dp[u][j]+dp[v][k]); } t+=now; } for(int i=1;i<=t+1;i++)//注意,这里就是题目的关键了,如果选择了父节点,那么父节点可以当成子树的所有状态值 dp[u][i]=min(dp[u][i],w[u]); return t+1; } int main() { char str[100],c[110]; while(scanf("%s",str)==1) { if(strcmp(str,"#")==0) break; n=atoi(str); scanf("%d",&m); getchar(); init(); for(int i=0;i<n;i++) { gets(s); int len=strlen(s),cc=0,t=0,a,b; for(int j=0;j<=len;j++) { if(s[j]!=' ' && s[j]!='\0') c[t++]=s[j]; if(s[j]==' '||s[j]=='\0') { cc++; c[t]='\0'; t=0; if(cc==1) a=GetNum(c); else if(cc==2) w[a]=atoi(c); else { b=GetNum(c); g[a].push_back(b); in[b]++; } } } } for(int i=1;i<=n;i++)//将森林转为树 { if(in[i]==0) g[0].push_back(i); } w[0]=INT_MAX;//0节点是自己添加的,它对应的花费应该设定为正无穷,这样就不会选择这个点了 dfs(0); printf("%d\n",dp[0][m]); } return 0; }
相关文章推荐
- POJ 3345 HDU 2415 Bribing FIPA(树形DP)
- HDU 2415 Bribing FIPA(树形背包)
- Bribing FIPA(树形DP)输入难,学会stringstream的用法,map的使用
- 【树形dp】hdu 2415 Bribing FIPA
- poj 3345 Bribing FIPA 【树形dp + 01背包】
- POJ 3345——Bribing FIPA(树形DP)
- POJ 3345 Bribing FIPA(树形DP)
- poj 3345 Bribing FIPA (树形背包dp | 输入坑)
- POJ3345 Bribing FIPA(树形DP)
- 树形DP______Bribing FIPA( POJ 3345 )
- poj 3345 Bribing FIPA(树形dp)
- HDU 2415 树形DP
- POJ 3345 Bribing FIPA / 树形DP
- POJ3345 Bribing FIPA(树形DP)
- Bribing FIPA(树形DP)
- poj 3345 Bribing FIPA (树形背包dp | 输入坑)
- POJ 3345 Bribing FIPA(树形DP)
- Bribing FIPA (树形dp)
- hdu 2242 考研路茫茫——空调教室 点强连通+树形dp
- hdu 4003 Find Metal Mineral 树形DP