POJ 3046
阿新 • • 發佈:2018-08-21
bar str copy %d name print 復制代碼 ant else
題目大意:螞蟻牙黑,螞蟻牙紅:有A只螞蟻,來自T個家族,分別記為ant[i]個。同一個家族的螞蟻長得一樣,但是不同家族的螞蟻牙齒顏色不同。任取n只螞蟻(S <= n <= B),求能組成幾種集合?
狀態:dp[i][j]:前i種中選j個可以組成的種數
決策:第i種選k個,k<=ant[i] && j-k>=0
轉移:dp[i][j]=Σdp[i-1][j-k]
#include<stdio.h> #include<string.h> int dp[1005][10050]; int num[10050]; int main(){ int n,m,a,b,x; while(scanf("%d%d%d%d",&n,&m,&a,&b)!=EOF){ memset(num,0,sizeof(num)); for(int i=0;i<m;i++){ scanf("%d",&x); num[x]++; } memset(dp,0,sizeof(dp)); for(int i=0;i<=num[1];i++) dp[1][i]=1; for(int i=2;i<=n;i++){ for(int j=0;j<=b;j++){ for(int k=0;k<=num[i];k++){ if(j>=k) { dp[i][j]+=dp[i-1][j-k]; dp[i][j]%=1000000; } } } } int ans=0; for(int i=a;i<=b;i++){ ans+=dp[n][i]; ans%=1000000; } printf("%d\n",ans); } return 0; }
還有一種
dp[i][j] = dp[i-1][j] + dp[i][j-1] - dp[i-1][j-ant[i]-1]
#include<iostream> using namespace std; #define MOD 1000000 int T, A, S, B; int ant[1005]; int dp[2][100000]; int ans; int main() { scanf("%d%d%d%d", &T, &A, &S, &B); for (int i = 1; i <= A; i++) { int aa; scanf("%d", &aa); ant[aa]++; } dp[0][0] = dp[1][0] = 1; for (int i = 1; i <= T; i++) for (int j = 1; j <= B; j++) if (j - ant[i] - 1 >= 0) dp[i % 2][j] = (dp[(i - 1) % 2][j] + dp[i % 2][j - 1] - dp[(i - 1) % 2][j - ant[i] - 1] + MOD) % MOD; //在取模時若出現了減法運算則需要先+Mod再對Mod取模,防止出現負數(如5%4-3%4為負數) else dp[i % 2][j] = (dp[(i - 1) % 2][j] + dp[i % 2][j - 1]) % MOD; for (int i = S; i <= B; i++) ans = (ans + dp[T % 2][i]) % MOD; printf("%d\n", ans); return 0; }
POJ 3046