题目如下:
输入样例:
6 5 3
1 1 2
1 2 3
1 1 3
2 3 5
5 4 2
5 1 2
输出样例:
2
思路 or 题解:
牵扯到选不选,而且选择达到的目标给的范围很小的时候,多半可以压缩状态。
而且这道题又问的是最少的包数,多半是压状dp。
算法:顺序枚举每一包糖果,然后枚举每一个状态,然后用糖果的状态去获得新状态,并且更新状态里的最少包数。
注意事项:
- 枚举状态的时候,一定要去掉不合法的状态。
AC 代码如下:
int n, m, k;
int dp[(1 << 20) + 9], s[109][29];
void solve()
{
cin >> n >> m >> k;
for (int i = 1; i <= n; i ++)
for (int j = 1; j <= k; j++)
cin >> s[i][j], s[i][j]--;
int go = (1 << m) - 1;
memset(dp, -1, sizeof dp);
dp[0] = 0;
for (int i = 1; i <= n; i++)
{
int t = 0;
for (int j = 1; j <= k; j++)
t |= (1 << s[i][j]);
for (int k = 0; k <= go; k++)
{
if (dp[k] == -1)
continue;
int f = k | t;
if (dp[f] == -1 || dp[f] > dp[k] + 1)
dp[f] = dp[k] + 1;
}
}
cout << dp[go] << '\n';
}
int main()
{
solve();
}