Codeforces Round #302 (Div. 1) C - Remembering Strings 状压dp

C - Remembering Strings

思路:最关键的一点是字符的个数比串的个数多。 然后就能状压啦。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PII pair<int, int>
#define y1 skldjfskldjg
#define y2 skldfjsklejg

using namespace std;

const int N = 1e5 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;

int val[20][20], cost[20][20], state[20][20];
int dp[1 << 20], n, m;
char s[30][30];
int main() {
    scanf("%d%d", &n, &m);
    for(int i = 0; i < n; i++) scanf("%s", s[i]);
    for(int i = 0; i < n; i++)
        for(int j = 0; j < m; j++)
            scanf("%d", &cost[i][j]);

    for(int i = 0; i < n; i++) {
        for(int j = 0; j < m; j++) {
            int mx = 0;
            for(int k = 0; k < n; k++) {
                if(s[i][j] == s[k][j]) {
                    val[i][j] += cost[k][j];
                    mx = max(mx, cost[k][j]);
                    state[i][j] |= 1 << k;
                }
            }
            val[i][j] -= mx;
        }
    }

    int up = (1 << n) - 1;
    memset(dp, inf, sizeof(dp));

    dp[0] = 0;
    for(int s = 0; s < up; s++) {
        for(int j = 0; j < n; j++) {
            if(!((s >> j)&1)) {
                for(int k = 0; k < m; k++) {
                    dp[s|(1 << j)] = min(dp[s|(1 << j)], dp[s] + cost[j][k]);
                    dp[s|state[j][k]] = min(dp[s|state[j][k]], dp[s] + val[j][k]);
                }
                break;
            }
        }
    }
    printf("%d\n", dp[up]);
    return 0;
}

/*

*/

 

posted @ 2018-09-14 14:36  NotNight  阅读(128)  评论(0编辑  收藏  举报