P1212 多米诺骨牌

一开始把所有骨牌设为上大下小,得到一个总差值tot,把它看作背包的总体积。

翻转每个骨牌对答案的影响是上下差值的两倍,把它作为每个物体的体积。

这道题要求用这些物品装到体积最大的情况下,最小的翻转次数。

特别地,我们统计上小下大的个数base作为背包的基础重量。

在进行dp时,选择了一件物品相当于进行一次翻转,如果这个物品原来没有被翻转过,就相当于翻转了一次,因此重量w设为1;如果这个物品之前已经被翻转,即已经被算进了base,因为最终未翻转,需要抵消掉,所以重量w设为-1.

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,x,y,base,tot,v[1003],w[1003],dp[1003][1003],vs[1003][1003];
 4 int main(){
 5     cin>>n;
 6     for(int i=1;i<=n;i++){
 7         cin>>x>>y;
 8       if(x>y){
 9           v[i]=2*(x-y);
10           w[i]=1;
11           tot+=x-y;
12         }
13         if(y>x){
14             v[i]=2*(y-x);
15             w[i]=-1;
16             tot+=y-x;
17         }
18     }
19     for(int i=1;i<=n;i++)
20       for(int j=1;j<=tot;j++){
21           dp[i][j]=dp[i-1][j];
22           vs[i][j]=vs[i-1][j];
23           if(vs[i-1][j-v[i]]||j-v[i]==0){
24               if(!vs[i][j]){
25                   dp[i][j]=dp[i-1][j-v[i]]+w[i];
26                   vs[i][j]=1;
27                 }
28                 else dp[i][j]=min(dp[i][j],dp[i-1][j-v[i]]);
29             }
30         }
31     for(int i=tot;i>=i;i--)
32       if(vs[n][i]){
33           cout<<base+dp[n][i];
34           return 0;
35         }
36 } 
View Code

猜你喜欢

转载自www.cnblogs.com/vv123/p/12375374.html