cf #568 (Div. 2) Playlist for Polycarp 状压dp

62 篇文章 0 订阅

题目链接:https://codeforces.com/contest/1185/problem/G1

 

题意:

       给你n首歌的长度以及歌曲类型,现在问你有多少种歌曲的组合使得,组合中歌曲总时长为已知T,且组合中每首歌最多只出现一次,没有出现同一类型的歌曲连续的情况。

做法:

       因为n最多为15,类型不超过三种,歌曲长度最多为15,且T最多为225,所以挺明显是状压dp的,状态也比较好想,dp[i][j]代表状态为i(即15首歌中听过为1,没听过为0)情况下,听过的最后一首歌类型为j的情况(因为要控制同一类型的歌不会连续出现),状态转移方程为dp[i][g[j]]=(dp[i][g[j]]+dp[i-(1<<j)][k])%mod;,当前for到的状态是i,歌曲是j,如果i中有j,那么就从没有j的状态转移过来,同时要求g[j]和k不同。

       脑子大概是不好使了,什么时候把答案进行增加一下子都没反应过来。


#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int maxn=(1<<15);
int n,T;
int t[20],g[20];
ll dp[maxn+5][3],sti[maxn+5];
int main(){
    scanf("%d%d",&n,&T);
    rep(i,0,n-1){
        scanf("%d%d",&t[i],&g[i]);
        g[i]--;
    }
    ll ans=0;
    for(int i=1;i<maxn;i++){
        for(int j=0;j<n;j++){
            if((i&(1<<j))==0) continue;
            sti[i]=sti[i-(1<<j)]+t[j];
            if(i==(1<<j)) dp[i][g[j]]=1;
            else {

                 for(int k=0;k<3;k++){
                    if(k==g[j]) continue;
                    dp[i][g[j]]=(dp[i][g[j]]+dp[i-(1<<j)][k])%mod;
                }
            }
        }
        if(sti[i]==T){
            rep(k,0,2){
                ans=(ans+dp[i][k])%mod;
            }
        }
    }

    printf("%lld\n",ans);
    return 0;
}

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值