Stay Hungry,Stay Foolish!

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

 

 

posted @ 2024-06-16 11:50  lightsong  阅读(55)  评论(0编辑  收藏  举报
Life Is Short, We Need Ship To Travel