题意:
题目意思很简单,就是一开始有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 2 33 33 3 */