码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces Round #568 (Div. 2) G1. Playlist for Polycarp (easy version) (状压dp)

时间:2019-06-22 10:50:27      阅读:91      评论:0      收藏:0      [点我收藏+]

标签:span   add   main   list   its   cout   题目   fine   style   

题目:http://codeforces.com/contest/1185/problem/G1

题意:给你n给选项,每个选项有个类型和价值,让你选择一个序列,价值和为m,要求连续的不能有两个相同的类型,相同的物]品不一样的顺序代表不同,问有多少个序列

思路:首先范围是15个,这里我们可以用状压来代表选择哪些物品,然后这里是说不能有连续相同的类型,这里我们贪心考虑不全,最开始我考虑的是组合数的插空法,当时

发现有很多细节,写不了,这样的话我们就只能改成dp,

我们设置dp[i][j]   代表i状态以j结尾的序列有多少个,这里我们用的是dp中 的我为人人形式

 

#include<bits/stdc++.h>
#define maxn 100005
#define mod 1000000007
using namespace std;
typedef long long ll;
ll n,m;
ll sum[1<<15],dp[1<<15][15];
ll a[15],b[15];
ll add(ll x,ll y){
    return x+y>=mod?x+y-mod:x+y; 
}
int main(){
    cin>>n>>m;
    for(int i=0;i<n;i++){
        cin>>a[i]>>b[i];
    }
    for(int i=0;i<(1<<n);i++){
        for(int j=0;j<n;j++){
            if((i>>j)&1) sum[i]+=a[j];
        }
    }
    for(int i=0;i<n;i++) dp[1<<i][i]=1;//最开始只有一件物品的时候都是序列数为1
    ll ans=0;
    for(int i=0;i<(1<<n);i++){
        if(sum[i]==m){
            for(int j=0;j<n;j++){
                if((i>>j)&1){
                    ans=add(ans,dp[i][j]); 
                }
            } 
        }
        for(int j=0;j<n;j++){
            if(!((i>>j)&1)) continue;
            for(int k=0;k<n;k++){
                if(j==k) continue;//这里用当前二进制位1结尾推出其他的二进制位
                if(!((i>>k)&1)&&b[j]!=b[k]) dp[i|(1<<k)][k]=add(dp[i|(1<<k)][k],dp[i][j]);    
            }
        }
    }
    cout<<ans;
}

 

Codeforces Round #568 (Div. 2) G1. Playlist for Polycarp (easy version) (状压dp)

标签:span   add   main   list   its   cout   题目   fine   style   

原文地址:https://www.cnblogs.com/Lis-/p/11067769.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!