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: [email protected]
 *===========================================*/
#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;
}


你可能感兴趣的:(动态规划,ACM-ICPC征途)