背包的思想,背包有两种选择:取和不取,本题是:取上方块还是取下方块
dp[i][j]表示面对前i个骨牌,使上方块总共获得j个点数时最少的旋转次数
dp[i][j]=min(dp[i-1][j-a[i]],dp[i-1][j-b[i]]+1)
#include<iostream> #include<cstring> using namespace std; int n,a[1005],b[1005];//a[]是上方块,b是下方块 int dp[1005][6005];//dp[i][j]表示面对前i个骨牌获得上方块总共获得j个点数的最小旋转次数 const int inf=999999;//组成不了j个点数就是inf void solve() { int i,j; int sum=0; cin>>n; for(i=1;i<=n;i++){ cin>>a[i]>>b[i]; sum=sum+a[i]+b[i]; } sum=(sum+1)/2; memset(dp,inf,sizeof(dp));//初始化 if(a[1]==b[1])dp[1][a[1]]=0; else { dp[1][a[1]]=0;dp[1][b[1]]=1;//预处理 } for(i=2;i<=n;i++)//面对前i件物品 for(j=1;j<=6*n;j++) { if(j>=a[i]&&j>=b[i])//能装上方块和下方块 dp[i][j]=min(dp[i-1][j-a[i]],dp[i-1][j-b[i]]+1); else if(j>=b[i]&&j<a[i])//只能装下方块 dp[i][j]=dp[i-1][j-b[i]]+1; else if(j>=a[i]&&j<b[i])//只能装上方块 dp[i][j]=dp[i-1][j-a[i]]; } int ans; for(i=sum;i>=1;i--) if(dp[n][i]<inf){ ans=dp[n][i]; break; } cout<<ans<<endl; } int main() { solve(); }