纯动归问题。
dp[i][j]:前i个字母共用了j个按键,最小的按键次数。
dp[i][j]=min(dp[k][j-1])(k<i);
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<vector>
#define LL long long
#define INF 1000000000
using namespace std;
vector<int>vec[1001];
char str[10001];
int n,m;
int a[10001];
char key[10001];
char let[10001];
int dp[101][101];
int vis[1001];
int nums[101][101];
void dos()
{
memset(vis,0,sizeof(vis));
int num=0;
int i,j,k,z;
for(i=0; i<101; i++)
{
for(j=0; j<101; j++)dp[i][j]=INF;
}
for(i=1; i<=m; i++)
{
num+=a[i]*i;
dp[1][i]=num;
}
for(i=1;i<=m;i++)
{
for(j=1;j<=i;j++)
{
int num=0;
for(k=j;k<=i;k++)
{
num+=a[k]*(k-j+1);
}
nums[j][i]=num;
}
}
for(j=2; j<=n; j++)
{
for(k=j; k<=m; k++)
{
for(i=1; i<k; i++)
{
int num=nums[i+1][k];
dp[j][k]=min(dp[j][k],dp[j-1][i]+num);
}
}
}
int ipos=m;
for(j=n-1; j>=1; j--)
{
for(i=1; i<ipos; i++)
{
int num=nums[i+1][ipos];
if(dp[j+1][ipos]==dp[j][i]+num)
{
vis[i]=1;
ipos=i;
break;
}
}
}
int st=0;
printf("%c: ",key[st]);
for(i=1;i<=m;i++)
{
printf("%c",let[i-1]);
if(vis[i])
{
cout<<endl;
st++;
printf("%c: ",key[st]);
}
}
cout<<endl;
cout<<endl;
}
int main()
{
int _,i,j;
scanf("%d",&_);
for(j=1;j<=_;j++)
{
scanf("%d%d",&n,&m);
scanf("%s",key);
scanf("%s",let);
for(i=1; i<=m; i++)scanf("%d",&a[i]);
printf("Keypad #%d:\n",j);
dos();
}
return 0;
}