題意:
題目意思很簡單,就是一開始有x只羊和y只狼,接著他們要過河,過河的規則是:船有一個容量只能裝n個動物,每次過河都至少有一個動物在船上,並且不管是在岸上還是船上都必須保證狼的數量小於等於羊的數量。現在問你讓所有動物過河的最少運算元。
題解:
這題用dp解,dp[i][j][2]表示左邊有i個狼,j個樣並且現在人在左邊0,右邊1的運算元。右邊的羊和狼用總數減掉就出來了。發現狀態轉移很難搞,試著用BFS維護狀態i,j,p,YY這樣的結論:根據BFS性質,最先從起點狀態也就是dp[x][y][0]到終點狀態dp[0][0][1]的路徑就是最少運算元對應的路徑。注意細節處理。
#include<iostream>#include<math.h>#include<stdio.h>#include<algorithm>#include<string.h>#include<vector>#include<queue>#include<map>#include<set>using namespace std;#define B(x) (1<<(x))typedef long long ll;void cmax(int& a,int b){ if(b>a)a=b; }void cmin(int& a,int b){ if(b<a)a=b; }const int oo=0x3f3f3f3f;const int MOD=1000000007;const int maxn=205;int x,y,n;int dp[maxn][maxn][2];struct Node{ int x,y,p; Node(){} Node(int x_,int y_,int p_){ x=x_; y=y_; p=p_; }};int DP(){ memset(dp,-1,sizeof dp); queue<Node>q; dp[x][y][0]=0; q.push(Node(x,y,0)); Node now,next; while(!q.empty()){ now=q.front();q.pop(); int lx=now.x; int ly=now.y; int rx=x-now.x; int ry=y-now.y; if(now.p==0){ for(int i=0;i<=lx&&i<=n;i++){ int l=0; int r=ly; if(i<lx)cmax(l,ly-lx+i); if(rx+i>0)cmin(r,rx-ry+i); for(int j=l;j<=r&&j<=n-i;j++){ if(dp[lx-i][ly-j][1]==-1&&i+j>0){ dp[lx-i][ly-j][1]=dp[lx][ly][0]+1; q.push(Node(lx-i,ly-j,1)); } } } }else{ for(int i=0;i<=rx&&i<=n;i++){ int l=0; int r=ry; if(i<rx)cmax(l,ry-rx+i); if(lx+i>0)cmin(r,lx-ly+i); for(int j=l;j<=r&&j<=n-i;j++){ if(dp[lx+i][ly+j][0]==-1&&i+j>0){ dp[lx+i][ly+j][0]=dp[lx][ly][1]+1; q.push(Node(lx+i,ly+j,0)); } } } } } return dp[0][0][1];}int main(){ //freopen("E:\\read.txt","r",stdin); while(scanf("%d %d %d",&x,&y,&n)!=EOF){ printf("%d\n",DP()); }return 0;}/**3 3 233 33 3*/