2006/1/15 ACM程序设计期末考试
题目大意:每个单词都有一个值,从A、B…到Z的值分别为1、2…到26
现在给你26个字母每个字母的个数,问:能找到多少个字母总价值<=50
的单词数。(单词排列顺序无关,ACM和CMA和AMC都视为同一个单词)
思路:很多人都是用母函数做的,这里说下动态规划的思想。
把A、B…到Z看做26种物品,每种物品的价值为1、2…到26,每种物品的
个数有num[i]个。现有一个容量为50的背包,问有多少种装法,能满足背
包中总价值<=50
过程:开个二维数组,一维26个表示字母种类,二维50个表示价值。最后
从1-50种统计个数。这里0个字母不是单词。
注意:初始化的时候dp[0][0] = 1。
因为我们初始化是未放物品时符合条件的最优解。
0个字母0容量的时候方案数为1
同理容量为0的时候,无论存在哪个字母,方案数都为0,因为状态转移方
程 dp[i][j] += dp[i-1][j-w[i]*k] 是递推的,每种字母方案数都是由上一种
字母得到的,所以不需要每种字母都初始化。
当然,也可以这样初始化:
for (i = 0; i <= 26; i++) dp[i][0] = 1;最终代码:
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; int w[30],num[30],dp[55][55]; int main() { int N; scanf("%d",&N); while(N--) { memset(w,0,sizeof(w)); memset(dp,0,sizeof(dp)); for(int i = 1; i <= 26; i++) { w[i] = i; scanf("%d",&num[i]); } dp[0][0] = 1;//0个字母,0容量的时候方案数为1 // for (i = 0; i <= 26; i++) // dp[i][0] = 1; for(int i = 1; i <= 26; i++)//有N种物品 { for(int j = 0; j <= 50; j++)//容量 { for(int k = 0; k <= num[i] && w[i]*k <= j; k++)//物品数量 dp[i][j] += dp[i-1][j-w[i]*k];//最优方案个数 } } int ans = 0; for(int i = 1; i <= 50; i++) ans += dp[26][i]; printf("%d\n",ans); } return 0; }