1. 程式人生 > >Codeforces Round #302 (Div. 1) C - Remembering Strings 狀壓dp

Codeforces Round #302 (Div. 1) C - Remembering Strings 狀壓dp

stat \n space scan name ont def long long mod

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; } /* */

Codeforces Round #302 (Div. 1) C - Remembering Strings 狀壓dp