标签:style blog http color os io strong 数据
题意:让你用1~n中k个不同的数组成s,求有多少种组法。
题解:
DFS或者DP或打表。
1.DFS 由于数据范围很小,直接dfs每种组法统计个数即可。
1 //#pragma comment(linker, "/STACK:102400000,102400000") 2 #include<cstdio> 3 #include<cmath> 4 #include<iostream> 5 #include<cstring> 6 #include<algorithm> 7 #include<cmath> 8 #include<map> 9 #include<set> 10 #include<stack> 11 #include<queue> 12 using namespace std; 13 #define ll __int64 14 #define usint unsigned int 15 #define mz(array) memset(array, 0, sizeof(array)) 16 #define minf(array) memset(array, 0x3f, sizeof(array)) 17 #define REP(i,n) for(int i=0;i<(n);i++) 18 #define FOR(i,x,n) for(int i=(x);i<=(n);i++) 19 #define RD(x) scanf("%d",&x) 20 #define RD2(x,y) scanf("%d%d",&x,&y) 21 #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z) 22 #define WN(x) printf("%d\n",x); 23 #define RE freopen("D.in","r",stdin) 24 #define WE freopen("1biao.out","w",stdout) 25 26 const int maxn=22; 27 bool h[maxn]; 28 int ans; 29 int n,k,s; 30 void dfs(int x,int sum,int start) { 31 if(sum>s) return; 32 if(x==k) { 33 if(sum==s) ans++; 34 return; 35 } 36 for(int i=start; i<=n; i++) { 37 if(h[i]==false) { 38 h[i]=true; 39 dfs(x+1,sum+i,i+1); 40 h[i]=false; 41 } 42 } 43 return; 44 } 45 46 int farm() { 47 memset(h,0,sizeof(h)); 48 ans=0; 49 dfs(0,0,1); 50 return ans; 51 } 52 53 int main() { 54 while(scanf("%d%d%d",&n,&k,&s)!=EOF) { 55 if(n==0 && k==0 && s==0) break; 56 //cout<<n<<‘,‘<<k<<‘,‘<<s<<endl; 57 printf("%d\n",farm()); 58 } 59 return 0; 60 }
2.DP
dp[i][k][j]代表用1~i中的数中的k个组成j的种类数。
dp[i][k][j]=dp[i-1][k][j] + dp[i-1][k-1][j-i],加号左边是继承1~i-1的种类数(因为1~i的种类数包括1~i-1的种类数),加号右边是给那些由k-1个数组成的种类加上i得到j的种类。
1 //#pragma comment(linker, "/STACK:102400000,102400000") 2 #include<cstdio> 3 #include<cmath> 4 #include<iostream> 5 #include<cstring> 6 #include<algorithm> 7 #include<cmath> 8 #include<map> 9 #include<set> 10 #include<stack> 11 #include<queue> 12 using namespace std; 13 #define ll __int64 14 #define usint unsigned int 15 #define mz(array) memset(array, 0, sizeof(array)) 16 #define minf(array) memset(array, 0x3f, sizeof(array)) 17 #define REP(i,n) for(int i=0;i<(n);i++) 18 #define FOR(i,x,n) for(int i=(x);i<=(n);i++) 19 #define RD(x) scanf("%d",&x) 20 #define RD2(x,y) scanf("%d%d",&x,&y) 21 #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z) 22 #define WN(x) printf("%d\n",x); 23 #define RE freopen("D.in","r",stdin) 24 #define WE freopen("1biao.out","w",stdout) 25 int n,k,s; 26 int dp[33][22][166]; 27 28 int main() { 29 int i,j,k; 30 int maxj; 31 mz(dp); 32 dp[0][0][0]=1; 33 for(i=1; i<=20; i++) { 34 for(k=0; k<=10; k++) { 35 dp[i][k][0]=dp[i-1][k][0]; 36 maxj=(i+i-k+1)*k/2;///此i和k能打到的最大的j 37 for(j=1; j<=maxj; j++) {///dp[i][k][j],用数1~i中的k个组成j的种类数 38 dp[i][k][j]=dp[i-1][k][j];///继承 39 if(j>=i) dp[i][k][j] += dp[i-1][k-1][j-i];///没i的状态加上i 40 } 41 } 42 } 43 while(scanf("%d%d%d",&n,&k,&s)!=EOF) { 44 if(n==0 && k==0 && s==0) break; 45 //cout<<n<<‘,‘<<k<<‘,‘<<s<<endl; 46 printf("%d\n",dp[n][k][s]); 47 } 48 return 0; 49 }
3.DP 空间降一维
dp[k][j]表示k个数组成j的种类数。
有一维要逆序for,防止同一i下重复计算。
1 //#pragma comment(linker, "/STACK:102400000,102400000") 2 #include<cstdio> 3 #include<cmath> 4 #include<iostream> 5 #include<cstring> 6 #include<algorithm> 7 #include<cmath> 8 #include<map> 9 #include<set> 10 #include<stack> 11 #include<queue> 12 using namespace std; 13 #define ll __int64 14 #define usint unsigned int 15 #define mz(array) memset(array, 0, sizeof(array)) 16 #define minf(array) memset(array, 0x3f, sizeof(array)) 17 #define REP(i,n) for(int i=0;i<(n);i++) 18 #define FOR(i,x,n) for(int i=(x);i<=(n);i++) 19 #define RD(x) scanf("%d",&x) 20 #define RD2(x,y) scanf("%d%d",&x,&y) 21 #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z) 22 #define WN(x) printf("%d\n",x); 23 #define RE freopen("D.in","r",stdin) 24 #define WE freopen("1biao.out","w",stdout) 25 int n,K,s; 26 int dp[12][166]; 27 28 int main() { 29 int i,j,k; 30 int maxj; 31 while(scanf("%d%d%d",&n,&K,&s)!=EOF) { 32 if(n==0 && K==0 && s==0) break; 33 mz(dp); 34 dp[0][0]=1; 35 for(i=1; i<=n; i++) {///用1到i中的数 36 for(k=K; k>0; k--) { 37 for(j=i; j<=s; j++) {///dp[k][j],k个数组成数j的种类数 38 dp[k][j] += dp[k-1][j-i];///没i的状态加上i 39 } 40 } 41 } 42 printf("%d\n",dp[K][s]); 43 } 44 return 0; 45 }
4.打表
深搜怕超时可以怒打一表,只要不限制代码长度就随便过。
(代码太长了贴不上来)
UvaLive6661 Equal Sum Sets dfs或dp,布布扣,bubuko.com
UvaLive6661 Equal Sum Sets dfs或dp
标签:style blog http color os io strong 数据
原文地址:http://www.cnblogs.com/yuiffy/p/3900099.html