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]); } } 
相關文章
相關標籤/搜索