• 【计蒜客习题】灌溉机器人


    问题描述


    农田灌溉是一项十分费体力的农活,特别是大型的农田。蒜头君想为农民伯伯们减轻农作负担,最近在研究一款高科技——灌溉机器人。它可以在远程电脑控制下,给农田里的作物进行灌溉。
    现在有一片 N 行 M 列的农田。农田的土壤有两种类型:类型 HH 和类型 PP,每一个格子上的土壤类型相同。其中类型 P 的土壤硬度较大,可以用来布置灌溉机器人,但是一个格子上只能布置一台。类型 H 的土壤不能布置灌溉机器人。一台灌溉机器人的灌溉区域如下图所示:

    黄色表示灌溉机器人布置的格子,红色表示其灌溉区域,即四个方向上各外扩展两个格子。
    蒜头君想在农田上尽可能多布置一些灌溉机器人,但是任意一台机器人不能在任意一台机器人的灌溉区域里,否则机器容易进水出故障。现在已知农田每个格子的土壤类型,请你来帮蒜头君计算一下,蒜头君最多能布置多少台灌溉机器人。


    输入格式


    输入第一行输入两个正整数N,M(N≤100,M≤10),表示农田的行和列。
    接下来输入 N 行,每行输入连续的 M 个字符(P或者H),中间没有空格。表示农田每个格子上的土壤类型。


    输出格式


    输出一行,输出一个整数,表示最多能摆放的灌溉机器人的数量

    样例输入

    3 4
    PHPP
    PHPP
    PHHP

    样例输出

    3


    呃呃,一道状压DP入门题。

    没什么好说的,注意先预处理一下,发现若要满足同一行不冲突,情况最多有60种。定义dp[i][j][k]表示处理到第i行,当前行选择方案为j,上一行选择方案为k时最多的摆放数量,这样就可以保证只需知道当前行的dp和上一行的dp就可以知道对当前行选择方案有影响的上一行和上上一行,转移方程显然是dp[i][j][k]=max{dp[i-1][k][l]+count(j)},count返回某一方案的机器人数量。再就是冲突时的判断需要写好。

     1 #include<cstdio>
     2 inline int max(int a,int b) {return a>b?a:b;}
     3 const int maxn=105,maxm=15;
     4 //经预先验证,满足同一行不冲突的情况最多有60种
     5 int n,m,map[maxn],state[65],cnt,dp[maxn][65][65],ans;
     6 bool judge1(int x) {
     7     return (x&(x>>1))==0&&(x&(x>>2))==0;
     8 }
     9 bool judge2(int i,int j) {
    10     return (j|map[i])==map[i];
    11 }
    12 bool judge3(int x,int y) {
    13     return (x&y)==0;
    14 }
    15 int count(int i) {
    16     int c=0;
    17     while(i) {
    18         if(i&1) ++c;
    19         i>>=1;
    20     }
    21     return c;
    22 }
    23 int main() {
    24     scanf("%d%d",&n,&m);
    25     for(int i=1;i<=n;++i) {
    26         int si=0;char c;
    27         for(int j=0;j<m;++j) {
    28             while((c=getchar())=='
    '||c==' '||c=='
    ');
    29             if(c=='P') si|=(1<<j);
    30         }
    31         map[i]=si;
    32     }
    33     for(int i=0;i<(1<<m);++i) if(judge1(i)) state[++cnt]=i;
    34     for(int i=1;i<=cnt;++i) if(judge2(1,state[i])) {
    35         int cnt_i=count(state[i]);
    36         for(int j=1;j<=cnt;++j) dp[1][i][j]=cnt_i;
    37     }
    38     for(int i=2;i<=n;++i)
    39         for(int j=1;j<=cnt;++j) if(judge2(i,state[j])) {
    40             int cnt_j=count(state[j]);
    41             for(int k=1;k<=cnt;++k) if(judge2(i-1,state[k])&&judge3(state[j],state[k]))
    42                 for(int l=1;l<=cnt;++l)
    43                     if(judge2(i-2,state[l])&&judge3(state[k],state[l])&&judge3(state[j],state[l]))
    44                         dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][l]+cnt_j);
    45         }
    46     for(int i=1;i<=cnt;++i)
    47         for(int j=1;j<=cnt;++j) ans=max(ans,dp[n][i][j]);
    48     printf("%d",ans);
    49     return 0;
    50 }
    AC代码
  • 相关阅读:
    eclipse A Java Runtime Environment(JRE)
    【Android】自己定义圆形ImageView(圆形头像 可指定大小)
    addEventListener()、attachEvent()和removeEventListener()、detachEvent()的差别?
    Android 自己定义控件实现刮刮卡效果 真的就仅仅是刮刮卡么
    qt自己定义搜索框(超简单,带效果图)
    OpenCV基础篇之像素操作对照度调节
    NYOJ 16 矩形嵌套 (DAG上的DP)
    hdu 1247 Hat’s Words(从给的单词中找hat&#39;s word 并按字典序输出)
    Android学习路线(十八)支持不同设备——支持不同的屏幕
    移动智能设备功耗优化系列--前言(NVIDIA资深project师分享)
  • 原文地址:https://www.cnblogs.com/Mr94Kevin/p/9635865.html
Copyright © 2020-2023  润新知