CodeForces 295C Greg and Friends :n个人在河一边,有一船载重最大k,求最少几次将人全部运过去并求出方案 :bfs+dp
n<=50 k<=5000,每个人要么50kg要么100kg
首先对于第一个问题可以进行bfs,节点保存dis[x1][x2][flag]表示河两岸x1个50kg,x2个100kg
如果i个50kg和j个100kg可以过河那对面就是dis[k1-x1+i][k2-x2+j][1-flag],最后ans为dis[k1][k2][1]
这个时候考虑第二个问题,如何求最少转移时候的方案,其实完全可以在bfs里面顺带求出来,因为只要从一个状态+1转移到另一个状态,那么另一个的方案数就可以加上当前状态的组合数相乘了=
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #include<queue> 5 using namespace std; 6 #define LL long long 7 #define MOD 1000000007 8 struct dian{ 9 LL x1,x2,flag; 10 }; 11 queue<dian>q; 12 LL dis[55][55][2],way[55][55][2],k,n,c[55][55]; 13 void bfs(LL k1,LL k2) 14 { 15 dian n1,n2; 16 LL i,j,tmp; 17 dis[k1][k2][0]=0; way[k1][k2][0]=1; 18 n1.x1=k1; n1.x2=k2; n1.flag=0; 19 while (!q.empty()) q.pop(); 20 q.push(n1); 21 while (!q.empty()) 22 { 23 n1=q.front(); q.pop(); 24 for (j=0;j<=n1.x2;j++) 25 { 26 if (j*100>k) break; 27 for (i=0;i<=n1.x1;i++) 28 { 29 if (i==0&&j==0) continue; 30 if (i*50+j*100>k) break; 31 n2.x1=((k1-n1.x1)+i); n2.x2=((k2-n1.x2)+j); 32 n2.flag=1-n1.flag; 33 if (dis[n2.x1][n2.x2][n2.flag]==-1) 34 { 35 dis[n2.x1][n2.x2][n2.flag]=dis[n1.x1][n1.x2][n1.flag]+1; 36 q.push(n2); 37 } 38 if(dis[n2.x1][n2.x2][n2.flag]==dis[n1.x1][n1.x2][n1.flag]+1) 39 { 40 tmp=c[n1.x1][i]*c[n1.x2][j]%MOD; 41 way[n2.x1][n2.x2][n2.flag]=(way[n2.x1][n2.x2][n2.flag]+ 42 tmp*way[n1.x1][n1.x2][n1.flag])%MOD; 43 } 44 } 45 } 46 } 47 } 48 int main() 49 { 50 LL i,j,k1,k2,x; 51 for (i=0;i<=50;i++) 52 { 53 c[i][0]=c[i][i]=1; 54 for (j=1;j<i;j++) c[i][j]=(c[i-1][j-1]+c[i-1][j])%MOD; 55 } 56 scanf("%lld%lld",&n,&k); 57 k1=k2=0; 58 memset(dis,-1,sizeof(dis)); 59 memset(way,0,sizeof(way)); 60 for (i=1;i<=n;i++){ 61 scanf("%lld",&x); 62 if (x==50) k1++; 63 else k2++; 64 } 65 bfs(k1,k2); 66 printf("%lld\n%lld\n",dis[k1][k2][1],way[k1][k2][1]); 67 return 0; 68 }