首页 > 代码库 > UvaLive 6661 Equal Sum Sets 二进制枚举/DP
UvaLive 6661 Equal Sum Sets 二进制枚举/DP
链接:http://vjudge.net/problem/viewProblem.action?id=49406
题意:根据给出的n,k,s求出n个数每个数都不大于k,和为s的序列(n个数每个都不同)的总情况数。
思路:
1.二进制枚举枚举出所有可能排列,并求和若和为s,则符合,否则不符合。
代码:
#include<iostream> #include<set> #include<map> #include<queue> #include<cstring> #include<string> #include<algorithm> #include<cstdio> using namespace std; int lim[25]; int init() { lim[0]=1; lim[1]=2; for(int i=2;i<=22;i++) lim[i]=lim[i-1]*2; } int main() { int n,k,s; init(); while(scanf("%d%d%d",&n,&k,&s)&&!(!n&&!k&&!s)) { int res=0; for(int i=0;i<lim[n];i++) { int ii=i; int all=0,kk=0; int ans=0; while(ii) { all++; if(ii%2==1) { kk++; ans+=all; } ii/=2; } if(ans==s&&kk==k) res++; } printf("%d\n",res); } return 0; }2.DP
状态转移方程:dp[i][j][k]=dp[i-1][j][k]+dp[i-1][j-i][k-1]
其中dp[i][j][k]表示不超过i的k个和为j的情况数。
dp[i-1][j][k]是指第i个不选择i的情况,dp[i-1][j-i][k-1]表示第个选择i,即前k-1个的和为j-i。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<map> #include<cstdlib> #include<queue> #include<stack> #include<vector> #include<ctype.h> #include<algorithm> #include<string> #define PI acos(-1.0) #define maxn 10005 #define INF 0x7fffffff typedef long long ll; using namespace std; int dp[25][160][15]; int init() { dp[0][0][0]=1; for(int i=1; i<=20; i++) { for(int j=0;j<=155;j++) { for(int k=0;k<=10;k++) { dp[i][j][k]=dp[i-1][j][k]; if(j>=i&&k>0) dp[i][j][k]+=dp[i-1][j-i][k-1]; } } } } int main() { int n,k,s; init(); while(scanf("%d%d%d",&n,&k,&s)) { if(n==0&&k==0&&s==0) break; printf("%d\n",dp[n][s][k]); } return 0; }
UvaLive 6661 Equal Sum Sets 二进制枚举/DP
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。