zoukankan      html  css  js  c++  java
  • HDU-1565 方格取数(1)

                 http://acm.hdu.edu.cn/showproblem.php?pid=1565                      

                                    方格取数(1)

    Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4740    Accepted Submission(s): 1798

    Problem Description
    给你一个n*n的格子的棋盘,每个格子里面有一个非负数。 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和最大。
     
    Input
    包括多个测试实例,每个测试实例包括一个整数n 和n*n个非负数(n<=20)
     
    Output
    对于每个测试实例,输出可能取得的最大的和
     
    Sample Input
    3
    75 15 21
    75 15 28
    34 70 5
     
    Sample Output
    188
    //dp[i][j]=max(dp[i-1][k]+curline); 其中(k & j ==0)
    //设dp[i][j]为取完前i行数中 第i行为二进制j状态的最大值
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int n,bit[1<<21];//存储合法状态
    int dp[2][1<<21];//滚动数组01之间转变。
    int top,m,map[21][21];
    void init()
    {
        int i,t=0;
        //得到符合题意的状态数 例如: 1011 & 10110(既1011 <<1 ) =1 可得1011不符合题意
        //state[]存储每一种合法状态
        for(i=0;i<top;i++)
        {
            if(i&(i<<1))
               continue;
            else
              {
                  bit[t++]=i;
              }
        }
    }
    int getsum(int i,int x)//状态为x
    {
         int sum=0,t=0;
        while(x)
        {
            if(x&1)
               sum+=map[i][t];
           x=x>>1;
            t++;
        }
        return sum;
    }
    int main()
    {
        int i,j,k,max,x;
      while(~scanf("%d",&n))
        {
               m=1<<n;
              
             top=1<<21;
             init();
         memset(dp,-1,sizeof(dp));
            for(i=0;i<n;i++)
             for(j=0;j<n;j++)
              scanf("%d",&map[i][j]);
            for(i=0;bit[i]<m;i++)
              dp[0][i]=getsum(0,bit[i]);//对第1行进行初始化
                for(i=1;i<n;i++) //遍历剩余数组
               {
                for(j=0;bit[j]<m;j++)//遍历所有状态
                  {
                    max=-9999;
                  for(k=0;bit[k]<m;k++)
                    {  //(i+1)&1无论怎么取都是0,1;
                       if(dp[(i+1)&1][k]!=-1&&(!(bit[j]&bit[k])))//保证上下不取。
                          {//遍历上一层的所有状态,求出最大值。
                              x=dp[(i+1)&1][k];
                                if(max<x)
                                   max=x;
                          }
                    }
                    dp[i&1][j]=max+getsum(i,bit[j]);
                }
             }
             max=-9999;
             i--;
         for(k=0;bit[k]<m;k++)
          {
            if(dp[i&1][k] >max)
            max = dp[i&1][k];
          }//遍历最后一行, 找最大值
        printf("%d
    ",max);
    
        }
        return 0;
    }
    /*
    3
    75 15 21
    75 15 28
    34 70 5
    */
    
     
  • 相关阅读:
    Java实现 LeetCode 236 二叉树的最近公共祖先
    Java实现 LeetCode 236 二叉树的最近公共祖先
    Java实现 LeetCode 235 二叉搜索树的最近公共祖先
    Java实现 LeetCode 235 二叉搜索树的最近公共祖先
    Java实现 LeetCode 235 二叉搜索树的最近公共祖先
    Java实现蓝桥杯打印图形
    Java实现蓝桥杯打印图形
    Java实现蓝桥杯打印图形
    C++ int与string的转化
    C语言:将16进制字符串转化为int类型值
  • 原文地址:https://www.cnblogs.com/cancangood/p/3753915.html
Copyright © 2011-2022 走看看