C - Popcorn
C - Popcorn
https://atcoder.jp/contests/abc358/tasks/abc358_c
思路1 -- 枚举法
遍历stands的所有组合, 对于每一种组合,判断是否满足全部的flavors, 满足则更新最小stands记录,
stands所有组合:
0
s1
s2
s3
s1,s2
s1,s3
s2,s3
s1,s2,s3
code1 -- 枚举法
https://atcoder.jp/contests/abc358/submissions/54627352
#define int long long int n, m; int stands[15]; string s[15]; signed main() { cin >> n >> m; for(int i=0; i<n; i++){ cin >> s[i]; for(int j=0; j<m; j++){ if (s[i][j] == 'o'){ stands[i] |= (1 << j); } } } /* iterate each combination of all stands, to check if they can meet all flavors, select the minumum number of stands. */ int minstands = n+1; for (int i=0; i<(1<<n); i++){ int acc = 0; for(int j=0; j<n; j++){ if (i & (1<<j)){ acc |= stands[j]; } } // meet all flavors if (acc == (1<<m)-1){ minstands = min(minstands, (long long)__builtin_popcount(i)); } } cout << minstands << endl; return 0; }
思路2 -- DP
思路1是离线思路,
思路2是在线思路。
定义dp[1<<m]为所有flavors组合的最小站满足数目。
dp[i] 解释:
i -- 为flavors的二进制表示, 011, 第二和第三个风味组合
dp[i] -- 为满足此风味组合,需要的最小站数目。
显然, 我们关心的是 dp[(1<<m)-1]。
如下有四种风味组合 :
F1 - 000
F2 - 001
F3 - 011
F4 - 100
遍历到一个站stands[i]时候, 每一种风味组合,在现有的基础上, 添加stands[i]带的风味,
如果stands[i] 没有带来新的风味, 状态转移为 dp[f2] --> dp[f2]
如果stands[i]带来了新的风味, 则当前风味总数要增加, dp[f2] --> dp[f3] 或者 dp[f4].
code2 -- DP
https://atcoder.jp/contests/abc358/submissions/54592215
#define int long long
int n, m;
/*
storing all flavors of each stand
*/
int stands[15];
string s[15];
/*
dp[i] --
for each flavors combination,
store the minumum number of stands.
*/
int dp[1<<15];
signed main()
{
cin >> n >> m;
for(int i=0; i<(1<<15); i++){
dp[i] = LLONG_MAX>>1;
}
// cout << dp[1] << endl;
dp[0] = 0;
for(int i=0; i<n; i++){
cin >> s[i];
for(int j=0; j<m; j++){
if (s[i][j] == 'o'){
stands[i] |= (1 << j);
}
}
/*
online caculate the minumum number of stands.
*/
for(int j=((1<<m)-1); j>=0; j--){
long long newflavors = j | stands[i];
dp[newflavors] = min(dp[newflavors], dp[j]+1);
}
}
cout << dp[(1<<m) - 1] << endl;
return 0;
}
出处:http://www.cnblogs.com/lightsong/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。