Codeforces Round #568 (Div. 2) G1. Playlist for Polycarp (easy version) (状压dp)
Posted lis-
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #568 (Div. 2) G1. Playlist for Polycarp (easy version) (状压dp)相关的知识,希望对你有一定的参考价值。
题目: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)的主要内容,如果未能解决你的问题,请参考以下文章
codeforces 568a//Primes or Palindromes?// Codeforces Round #315 (Div. 1)
Codeforces Round #568 (Div. 2) F - Two Pizzas (状态压缩,暴力)
Codeforces Round #568 (Div. 2) G1. Playlist for Polycarp (easy version) (状压dp)