您的位置:首页 > 其它

ZJU2025 I-Keyboard - 动态规划

2008-04-29 17:59 155 查看
题目大意:

在手机键盘N个按键上布置K个字符(1<=N<=K<=90),每个按键上可以布置任意多个字符,字符在键盘上的布局必须按照字符顺序。在手机上输入某个字符需要按键的次数等于这个字符在这个按键上排列的位置pi(和日常手机规则一样),每个字符都有一个使用频率fi,那么输入一个字符的平均费用为pi×fi。要求输出一种手机字符按键的布局方案,使得总平均输入费用最小。

分析:

题目好长,打开网页就没有读下去的欲望……

典型的动态规划题目。很多年前的动态规划看起来都很简单的样子。

令f[i][j]表示前i个按键以字符j结尾,所需要的最小费用。

令price(i,j)表示字符i到j连续排列到同一个按键上需要的费用。

初始时f[1]
=price(1,n)


状态转移方程:f[i][j]=min{ f[i-1][k]+price(k+1,j) } (i-1<=k<j)

----------------------------------------------------------------------------------
/*
ZJU2025 I-Keyboard
*/

#include <stdio.h>
#include <string.h>
#define clr(a) memset(a,0,sizeof(a))

#define N 105

char keys
,letters
;
int a
,f

,g

;
int n,m;

int price(int a[],int l,int r){
int i,s=0;
for(i=l;i<=r;i++){
s+=a[i]*(i-l+1);
}
return s;
}

void prints(char s[],int l,int r){
int i;
for(i=l;i<=r;i++) printf("%c",s[i]);
}

void output(int key,int letter){
if(key>1){
output(key-1,g[key][letter]);
}
printf("%c: ",keys[key-1]);
prints(letters,g[key][letter],letter-1);
puts("");
}

int main()
{
int i,j,k,T,Tn;
int e,s;

scanf("%d",&Tn);
for(T=1;T<=Tn;T++){
//input
scanf("%d%d",&n,&m);
scanf("%s %s",keys,letters);
for(i=1;i<=m;i++)
scanf("%d",&a[i]);

//init
clr(f); clr(g);

//DP
for(j=1;j<=m;j++) f[1][j]=price(a,1,j);
for(i=2;i<=n;i++){
for(j=1;j<=m;j++){
f[i][j]=f[i-1][i-1]+price(a,i,j);
g[i][j]=i-1;
for(k=i;k<j;k++){
s=f[i-1][k]+price(a,k+1,j);
if(f[i][j]>s){
f[i][j]=s;
g[i][j]=k;
}
}
}
}

//output
printf("Keypad #%d:/n",T);
for(i=j=1;i<=n;i++){
if(f[i][m]<f[j][m]) j=i;
}
output(n,m);
puts("");
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: