洛谷P1282 多米诺骨牌 dp

背包的思想,背包有两种选择:取和不取,本题是:取上方块还是取下方块

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();
}

猜你喜欢

转载自www.cnblogs.com/lyhhahaha/p/10004276.html