CF295C Greg and Friends

首先

咱们考虑每次船来回运人时均可以当作一种dp状态c++

又由于人的体重只有50kg和100kg两种,数组

因此咱们能够开一个三维数组dp[i][j][k],第1维表示在出发岸50kg有i个,第2维表示在出发岸100kg有j个,第3维表示船在哪一岸函数

又考虑到每个人都是不一样的,因此咱们须要对在船岸的这一边的人数和上船的人数去组合数,能够打一个杨辉三角的表b[i][j],用来快速查询组合数spa

因此状态转移就能够枚举在此岸上船50kg和100kg的人数并取组合数乘上本身的原值(乘法原理)code

其次

本题还要求求最短运送次数,咱们就能够用广搜来遍历枚举答案blog

同理dp的状态转移也能够在广搜中一块儿完成队列

#include <bits/stdc++.h>
#define ll long long
using namespace std; struct kk { ll i,j,k; }sh[1000001];//数组模拟队列 
ll n,w,step[100][100][3],dp[100][100][3]; ll a[100],t50,t100,b[1000][1000],mod; void bfs(ll i1,ll j1,ll wh) { ll l,r; l=0;r=0; sh[l].i=i1; sh[l].j=j1; sh[l].k=wh; r++; while (l<r) { ll nowi,nowj,nowh; nowi=sh[l].i; nowj=sh[l].j; nowh=sh[l].k; l++; if (nowh==1)//枚举出发岸 
        for (ll x=0;x<=nowi;x++) { for (ll y=0;y<=nowj;y++) { if (50*x+100*y>w || (x==0 && y==0)) continue;//判断体重是否超过船载重 
 ll xi,xj,xwh; xi=nowi-x; xj=nowj-y; xwh=1-nowh; if (step[xi][xj][xwh]!=0)//重点,此处与通常的广搜不一样,当一种状态被遍历过了不能直接标记掉,还要取最优状况 
 { if (step[nowi][nowj][nowh]+1<step[xi][xj][xwh]) step[xi][xj][xwh]=step[nowi][nowj][nowh]+1; if (step[nowi][nowj][nowh]+1==step[xi][xj][xwh])//步数相同时,更新dp值 
 { dp[xi][xj][xwh]+=(b[nowi+1][x+1]%mod)*(b[nowj+1][y+1]%mod)*(dp[nowi][nowj][nowh]%mod); dp[xi][xj][xwh]%=mod; } } else { dp[xi][xj][xwh]=(b[nowi+1][x+1]%mod)*(b[nowj+1][y+1]%mod)*(dp[nowi][nowj][nowh]%mod); dp[xi][xj][xwh]%=mod; step[xi][xj][xwh]=step[nowi][nowj][nowh]+1; sh[r].i=xi; sh[r].j=xj; sh[r].k=xwh; r++; } } } if (nowh==0)//枚举对岸 
        for (ll x=0;x<=t50-nowi;x++) { for (ll y=0;y<=t100-nowj;y++) { if (50*x+100*y>w || (x==0 && y==0)) continue; ll xi,xj,xwh; xi=nowi+x; xj=nowj+y; xwh=1-nowh; if (step[xi][xj][xwh]!=0) { if (step[nowi][nowj][nowh]+1<step[xi][xj][xwh]) step[xi][xj][xwh]=step[nowi][nowj][nowh]+1; if (step[nowi][nowj][nowh]+1==step[xi][xj][xwh]) { dp[xi][xj][xwh]+=(b[t50-nowi+1][x+1]%mod)*(b[t100-nowj+1][y+1]%mod)*(dp[nowi][nowj][nowh]%mod); dp[xi][xj][xwh]%=mod; } } else { dp[xi][xj][xwh]=(b[t50-nowi+1][x+1]%mod)*(b[t100-nowj+1][y+1]%mod)*(dp[nowi][nowj][nowh]%mod); dp[xi][xj][xwh]%=mod; step[xi][xj][xwh]=step[nowi][nowj][nowh]+1; sh[r].i=xi; sh[r].j=xj; sh[r].k=xwh; r++; } } } } } int main() { scanf("%lld%lld",&n,&w); for (ll x=1;x<=n;x++) scanf("%lld",&a[x]); memset(dp,0,sizeof(dp)); memset(step,0,sizeof(step)); for (ll x=1;x<=n;x++) { if (a[x]==50) t50++; if (a[x]==100) t100++; } b[1][1]=1; for (ll x=2;x<=50;x++) { for (ll y=1;y<=x;y++) b[x][y]=b[x-1][y]+b[x-1][y-1];//杨辉三角
 } mod=1000000007; dp[t50][t100][1]=1;//令1表示出发岸,0表示到达岸
    step[t50][t100][1]=0;//初始化
    bfs(t50,t100,1);//广搜函数 
    if (step[0][0][0]==0)//如何到达的步数为0就不能到达
 { printf("-1\n"); printf("0\n"); } else { printf("%lld\n",step[0][0][0]);//答案即为出发岸无人且船在对岸的状况
        printf("%lld\n",dp[0][0][0]); } } 
相关文章
相关标签/搜索