Codeforces Round #179 (Div. 1) C. Greg and Friends(BFS 或者最短路)
题目大意
有 n(1≤n≤50) 个人,每个人的体重要么是 50,要么是 100。现在他们都在河岸的一边,有一条船,最大栽种量为 K(1≤k≤5000),问:把所有人从河这岸运送到河对岸去,最少需要划船多少次,以及共有多少种不同的坐船方案使得划船次数最少
做法分析
注意题目给出的条件,每个人的重量要么是 50 要么是 100,大家肯定都注意到这点了,怎么利用呢?这样考虑:
在某个时刻,重量为 50 的人有多少个,重量为 100 的人有多少个,他们是在河的哪一边?
想到这里,大家肯定就有思路了,可以 BFS,也可以求最短路,这样,最少需要划船的次数就求出来了
至于多少种方案,BFS 或者求最短路的过程中再维护一个到达这个状态需要的划船的次数的信息即可
我用的 BFS 做的
参考代码
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <queue> 5 6 using namespace std; 7 8 typedef long long LL; 9 const int N=56, MOD=1000000007; 10 11 struct node 12 { 13 int x, y, id; 14 node(int a, int b, int c):x(a), y(b), id(c) {} 15 }; 16 queue <node> q; 17 LL g[N][N][2]; 18 int f[N][N][2], n, m1, m2, k; 19 int C[N][N]; 20 21 void BFS() 22 { 23 memset(f, -1, sizeof f); 24 memset(g, 0, sizeof g); 25 f[m1][m2][0]=0, g[m1][m2][0]=1; 26 while(!q.empty()) q.pop(); 27 q.push(node(m1, m2, 0)); 28 while(!q.empty()) 29 { 30 node cur=q.front(); 31 q.pop(); 32 int k1=cur.x, k2=cur.y, id=cur.id; 33 for(int i=0; i<=k1; i++) 34 for(int j=0; j<=k2; j++) 35 { 36 if(i==0 && j==0) continue; 37 if(i*50+j*100>k) continue; 38 int x=m1-k1+i, y=m2-k2+j; 39 if(f[x][y][id^1]==-1) 40 { 41 f[x][y][id^1]=f[k1][k2][id]+1; 42 g[x][y][id^1]=(g[x][y][id^1]+C[k1][i]*g[k1][k2][id]%MOD*C[k2][j]%MOD)%MOD; 43 q.push(node(x, y, id^1)); 44 } 45 else if(f[x][y][id^1]==f[k1][k2][id]+1) 46 g[x][y][id^1]=(g[x][y][id^1]+C[k1][i]*g[k1][k2][id]%MOD*C[k2][j]%MOD)%MOD; 47 } 48 } 49 } 50 51 int main() 52 { 53 memset(C, 0, sizeof C); 54 for(int i=0; i<N; i++) C[i][0]=1; 55 for(int i=1; i<N; i++) 56 for(int j=1; j<=i; j++) C[i][j]=(C[i-1][j]+C[i-1][j-1])%MOD; 57 58 scanf("%d%d", &n, &k); 59 m1=0, m2=0; 60 for(int i=0, a; i<n; i++) 61 { 62 scanf("%d", &a); 63 if(a==50) m1++; 64 else m2++; 65 } 66 BFS(); 67 printf("%d\n%I64d\n", f[m1][m2][1], g[m1][m2][1]); 68 return 0; 69 }
题目链接 & AC通道
Codeforces Round #179 (Div. 1) C. Greg and Friends