uva 11552 - Fewest Flops ( 多维dp )


本文出自   http://blog.csdn.net/shuangde800



题目: 点击打开链接


题意

给一个字符串,把它分为k块,例如字符串“helloworld”分成2块,"hello", "world"

每一块里面的字母可以任意的排序。

最终字符串, 连续的一样的字母算作一个chunk,问总chunks最少是多少?



思路

f[i][j]: 第i块的第j位排在最后一位的最少chunks


对于每个单独的一块,它的chunks就是等于出现的不同字母数

第i块的chunks记做 chunks[i]


如果第i-1块的最后一位和第i块的第一位是一样的,那么可以合并这两个,总chunks可以减少一个


f[i][j] = min{  如果i-1块的第k位和i块的第一位不同:  f[i-1][k]+chunks[i], 
                   如果i-1块的第k位和i块的第一位相同:  f[i-1][k]+chunks[i]-1  }


代码

/**==========================================
 *   This is a solution for ACM/ICPC problem
 *
 *   @source:uva-11552 Fewest Flops
 *   @type:  dp
 *   @author: shuangde
 *   @blog: blog.csdn.net/shuangde800
 *   @email: zengshuangde@gmail.com
 *===========================================*/
#include
   
   
    
    
#include
    
    
     
     
#include
     
     
      
      
#include
      
      
       
       
#include
       
       
         #include 
        
          #include 
         
           using namespace std; typedef long long int64; const int INF = 0x3f3f3f3f; const int MAXN = 1010; int k; char str[MAXN]; int f[MAXN][MAXN]; bool vis[130]; int main() { int nCase; scanf("%d", &nCase); while (nCase--) { scanf("%d %s", &k, str); int len = strlen(str); // init memset(f, INF, sizeof (f)); for (int i = 0; i < len / k; ++i) { // 算出Si有几个chunks int chunks = 0; memset(vis, 0, sizeof (vis)); for (int j = i * k; j <= (i + 1) * k - 1; ++j) { vis[str[j]] = true; } for (int j = 'a'; j <= 'z'; ++j) if (vis[j]) ++chunks; if (i == 0) { for (int j = 0; j < k; ++j) f[i][j] = chunks; continue; } for (int j = 0; j < k; ++j) { int rear = i * k + j; for (int l = 0; l < k; ++l) { int pre = (i - 1) * k + l; if (vis[str[pre]] && (chunks == 1 || str[pre] != str[rear])) { f[i][j] = min(f[i][j], f[i - 1][l] + chunks - 1); } else { f[i][j] = min(f[i][j], f[i - 1][l] + chunks); } } } } int ans = INF; for (int i = 0; i < k; ++i) ans = min(ans, f[len / k - 1][i]); printf("%d\n", ans); } return 0; } 
          
         
       
      
      
     
     
    
    
   
   


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值