洛谷P1282 多米诺骨牌
Topic Links
Topic Meaning:有n个骨牌,骨牌有带有相应点数的上下俩部分,这n个骨牌的上部分和与下部分和之差的绝对值为m,骨牌可以翻转,即上部分点数与下部分点数交换,则得到最下的m的所需的翻转次数为多少?
Topic of Solving:线性背包
以第i个骨牌为阶段,前i个骨牌上下部分和的差值为状态,分别对翻与不翻进行状态转移
dp[i][j]表示前i个骨牌m为j;
由于差值可为负值,再结合题目的数据范围,故将表示状态的差值均增大5000,故dp[0][5000]=0为初始状态即前0个骨牌差值为0需翻0次;
从5000即差值为0往两边寻找第一个翻转数小于最大翻转次数1000(即可通过状态转移得到的差值),再判断此差值绝对值的最小翻转数即可;
#include#include using namespace std; int a[1005],b[1005],dp[1005][10000]; int main(){ int n; cin>>n; for(int i=1;i<=n;i++) cin>>a[i]>>b[i]; memset(dp,0x7F,sizeof(dp)); dp[0][5000]=0; for(int i=1;i<=n;i++) for(int j=10000;j>=0;j--){ int dis=a[i]-b[i]; if(j-dis<=10000&&j-dis>=0) dp[i][j]=min(dp[i][j],dp[i-1][j-dis]); if(j+dis>=0&&j+dis<=10000) dp[i][j]=min(dp[i][j],dp[i-1][j+dis]+1); } for(int j=0;;j++) if(dp[n][5000+j]<=1000||dp[n][5000-j]<=1000){ if(dp[n][5000+j]