ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF1082F - Speed Dial

2021-05-08 19:01:16  阅读:213  来源: 互联网

标签:Dial LCP int text rep CF1082F dep Speed dp


CF1082F - Speed Dial

题目大意

给定\(n\)个电话号码,你可以随意生成\(k\)个快捷键,每个快捷键是一个数字串

最终拨号方式:

选择 至多一个 快捷键按下,对于剩余部分手动补全,且不允许退格

每个电话号码有拨打次数,最小化手动补全部分的长度总和


分析

如果每次选定一个集合使其公用一个快捷键,那么其长度必然是集合中所有串的\(\text{LCP}\)

假设确定了一个\(\text{LCP}\),那么对应的串集合容易发现就是\(\text{trie}\)树上的一个子树

于是先将所有串加入\(\text{trie}\)树,此时问题转化为

选择至多\(k\)个\(\text{LCP}\)(默认根节点选了且没有代价),使得每个电话号码到其祖先中最深\(\text{LCP}\)的距离之和最小

由于有拨打次数的限制,且其数值相对较大,难以存入dp状态

于是想到在祖先钦定\(\text{LCP}\),然后从子树取值

令\(dp_{u,i,j}\)表示计算\(u\)子树内的答案,已经钦定祖先中最深的\(\text{LCP}\)长度为\(i\),且在子树内又钦定了\(j\)个\(\text{LCP}\)

合并子树时对于每个\(i\),背包合并\(j\),决策\(u\)自己是否选为\(\text{LCP}\)即可

const int N=510,INF=1e9+10;

int n,m;
int trie[N][10],cnt,c[N];
char s[N];
int dp[N][N][12];
int F[N][12],G[12],dep[N];

void dfs(int u) {
	for(int v:trie[u]) if(v) dep[v]=dep[u]+1,dfs(v);
	memset(F,63,sizeof F);
	rep(i,0,dep[u]) F[i][0]=c[u]*(dep[u]-i);
	for(int v:trie[u]) if(v) {
		rep(j,0,dep[u]) {
			rep(k,0,m) G[k]=F[j][k],F[j][k]=INF;
			rep(k,0,m) rep(d,0,m-k) cmin(F[j][k+d],G[k]+dp[v][j][d]);
		}
	}
	rep(d,0,dep[u]) {
		rep(i,0,m) dp[u][d][i]=INF;
		rep(i,0,m) {
			cmin(dp[u][d][i+1],F[dep[u]][i]);
			cmin(dp[u][d][i],F[d][i]);
		}
	}
}

int main(){
	n=rd(),m=rd();
	rep(i,1,n) {
		scanf("%s",s+1);
		int u=0;
		for(int j=1;s[j];++j) {
			int &v=trie[u][s[j]-'0'];
			if(!v) v=++cnt;
			u=v;
		}
		c[u]+=rd();
	}
	dfs(0);
	int ans=INF;
	rep(i,0,m) cmin(ans,dp[0][0][i]);
	printf("%d\n",ans);
}

标签:Dial,LCP,int,text,rep,CF1082F,dep,Speed,dp
来源: https://www.cnblogs.com/chasedeath/p/14746184.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有