zoukankan      html  css  js  c++  java
  • Codeforces 981D Bookshelves 【dp】【性质】

    这道题需要一点贪心,我们要找到每个书架价值&起来的最大值。从此出发可以想到最大值在二进制意义下如果高位可以取1,那么高位取1的数一定比高位不取1的数要大。如10000000大于01111111

    因此不难想到我们从最高位往下枚举每一位就可以了,那么我们现在要解决的问题是给一个数x,让我们判断n本书放在k个书架里能不能找到一个放的方式使得每个书架价值&起来是x

    由此想到用dp,我们dp[i][j],代表前i本书放进前j个书架里&价值能不能等于x(注意到实现的时候要在递归函数里带个参数x)。那转移方程怎么写呢?

    我们枚举k (k从j-1到i-1) ,如果dp(k,j-1,x) && ((sum[i]-sum[k])&x)==x,那dp[i][j]=1

    本质上我们枚举最后一个书架上放书的数量。比如我们遇到一个问题7本书放在5个书架里能不能&起来是x,那就是看( 4本书放在4个书架里,第五个书架放第5,6,7本书),( 5本书放在4个书架里,第五个书架放第6,7本书),( 6本书放在4个书架里,第五个书架放第7本书)这三个方案有没有任何一个方案使得书架&起来是x,如果有的话那returnn dp[7][5]=1

    最后考虑边界情况,如果j=1,那么 if( (sum[i]&x) ==x) return dp[i][j]=1 不然是0

    这里解释下sum[i]&x==x的意思,他指的是第一个书架放前i本书,判断书架价值&x等不等于x,如果等于x的话能就是合理的放书方式。

     1 #include<iostream>
     2 #include<cstring>
     3 using namespace std;
     4 
     5 long long sum[55],ans;
     6 int dp[55][55];//前i个书放进k个书架里&起来能不能等于check里的x
     7 
     8 bool check(int i,int j,long long x){
     9     if(dp[i][j]!=-1) return dp[i][j];
    10     if(j==1){
    11         if( (sum[i]&x) ==x) return dp[i][j]=1;
    12         return dp[i][j]=0;
    13     }
    14     for(int k=j-1;k<i;k++){
    15         if( check(k,j-1,x) && ((sum[i]-sum[k])&x)==x ) return dp[i][j]=1;
    16     }
    17     return dp[i][j]=0;
    18 } 
    19 
    20 int main(){
    21     int n,k; cin>>n>>k;
    22     for(int i=1;i<=n;i++) { cin>>sum[i]; sum[i]+=sum[i-1]; }
    23     
    24     for(int i=60;i>=0;i--){//枚举ans在二进制下的每一位
    25         memset(dp,-1,sizeof(dp));
    26         long long a=1; a=a<<i;
    27         if( check(n,k,ans+a) ) ans+=a;
    28     }
    29     cout<<ans<<endl;
    30     
    31     return 0;
    32 }
  • 相关阅读:
    ASP.NET MVC 学习笔记 1
    安装xp遇到的问题与如何连接共享的打印机
    win8.1 安装
    AspxGridView控件的使用
    JS获取fileupload文件全路径
    正则表达式的学习
    回归起点
    Vmware ESX 5.0 安装与部署
    UITextField检测输入内容不能有空格的处理
    关于cell自动布局约束实现高度自适应问题
  • 原文地址:https://www.cnblogs.com/ZhenghangHu/p/9109800.html
Copyright © 2011-2022 走看看