P3695清洁机器人
Time Limit : 1000MS Memory Limit : 65536 KB
Description
NK中学有n间教室(编号1到n),通过n-1条双向道路相连,每条道路的长度可能不同。现在有k台清洁机器人位于s号教室,现在要安排它们去清洁所有教室。
机器人靠燃油驱动,一台机器人清洁一个教室的耗油1升。在道路上行走时,每单位距离耗油1L。
我们希望完成清洁作业消耗的总油量尽可能少。请你计算出这个总油量。
作业结束时,机器人可以停留在任何位置。
Input Format
第一行,三个整数n,s,k
接下来n-1行,每行三个整数a,b,c,表示教室a和教室b之间有条长度为c的道路相连。
Output Format
一行,一个整数,表示所求答案。
Sample Input 1
3 1 1
1 2 1
1 3 1
Sample Output 1
6
Sample Input 2
3 1 2
1 2 1
1 3 1
Sample Output 2
5
Hint
样例1说明,机器人的活动线路为1->2->1->3,路上耗费3L燃油,清洁教室耗费3L
1<=n<=10000, 1<=s<=N, 1<=k<=10
Time Limit : 1000MS Memory Limit : 65536 KB
Description
NK中学有n间教室(编号1到n),通过n-1条双向道路相连,每条道路的长度可能不同。现在有k台清洁机器人位于s号教室,现在要安排它们去清洁所有教室。
机器人靠燃油驱动,一台机器人清洁一个教室的耗油1升。在道路上行走时,每单位距离耗油1L。
我们希望完成清洁作业消耗的总油量尽可能少。请你计算出这个总油量。
作业结束时,机器人可以停留在任何位置。
Input Format
第一行,三个整数n,s,k
接下来n-1行,每行三个整数a,b,c,表示教室a和教室b之间有条长度为c的道路相连。
Output Format
一行,一个整数,表示所求答案。
Sample Input 1
3 1 1
1 2 1
1 3 1
Sample Output 1
6
Sample Input 2
3 1 2
1 2 1
1 3 1
Sample Output 2
5
Hint
样例1说明,机器人的活动线路为1->2->1->3,路上耗费3L燃油,清洁教室耗费3L
1<=n<=10000, 1<=s<=N, 1<=k<=10
1<=c<=1000000.
设定状态:状态dp[u][j]为以u为根的子树,结束时有j个机器人留在了该子树中,所有机器人走的距离之和的最小值。
状态转移分析:
1.没有机器人留在该子树中:dp[u][0]= ∑(dp[v][0]+2*Len[u][v])其中V为u的儿子节点,Len[u][v]表示u到儿子v的边长。最终所有机器人都离开了u为根的子树,故该子树每条边都被经过了2次。
2.有机器人留在子树中:dp[u][j]=min(dp[u][j−t]+dp[v][t]+t*Len[u][v]) 0≤t≤j , 0≤j≤K
其中dp[v][t]表示将t个机器人分配给v号儿子,因此u点还剩下j-t个儿子
由于dp[v][t]+dp[u][j-t]中并没有包含从u走到v的边的消耗量,由于走了t个机器人,所以要加上t*len[u][v]
#include<cstdio>
#include<iostream>
using namespace std;
const int maxn=10005;
int n,s,k,cnt;
long long f[maxn][13];
int LEN[2*maxn],NEXT[2*maxn],LAST[maxn],END[2*maxn];
void insert(int a,int b,int l){
END[++cnt]=b;
LEN[cnt]=l;
NEXT[cnt]=LAST[a];
LAST[a]=cnt;
}
void dp(int u,int fa){
int i,j,t,q,v;
for(i=LAST[u],v=END[i];i;i=NEXT[i],v=END[i]){
if(v==fa)continue;
dp(v,u);
for(j=k;j>=0;j--){//j要逆序枚举,想一想为什么
f[u][j]+=f[v][0]+2*LEN[i];
////////相当于f赋值为无穷大,最后当j等于0就是之前讨论的p[u][0]=∑(dp[v][0]+2*Len[u][v])
for(t=0;t<=j;t++)
f[u][j]=min(f[u][j],f[v][t]+f[u][j-t]+t*LEN[i]);
}
}
}
int main(){
scanf("%d%d%d",&n,&s,&k);
int i,j,x,y,z;
for(i=1;i<n;i++){
scanf("%d%d%d",&x,&y,&z);
insert(x,y,z);
insert(y,x,z);
}
dp(s,-1);
cout<<f[s][k]+n;//f数组只讨论了边,最后要加上n个教室的消耗
}