首页 > 其他分享 >P3622 [APIO2007] 动物园 -题解

P3622 [APIO2007] 动物园 -题解

时间:2024-04-03 11:55:55浏览次数:25  
标签:ch int 题解 APIO2007 动物 啊啊啊 P3622

好写 爱写 没事干 所以有了这篇题解


洛谷P3622 [APIO2007] 动物园 题解

$Link$

hzoi题库
洛谷

题目说的挺繁琐,其实就传达了一个很简单的信息:

\(n\)个动物,\(c\)个小孩,每个小孩能看到\(5\)个动物(所在的位置)\(E\)到\(E+4\),有\(F\)个害怕的动物,\(L\)个喜欢的动物。如果视野中有至少一个喜欢的动物,或者讨厌的动物被移走至少一个,他就会高兴。你可以任意移走动物,求最多有几个小孩高兴。

由于每个视野固定长度为\(5\),所以只要状压每五个动物被移走的状态即可,枚举范围为\(0\) ~ \(2^5-1\),即\(0\) ~ \(31\)。

输入的时候做好初始化工作,得到数组\(num[N][S]\),表示从\(N\)开始5个动物在\(S\)状态下高兴的孩子数。

然后整个循环遍历一遍,状态转移方程为:

\[f[i][k] = max (f[i-1] [(j\And15)<<1],f[i-1][(j\And15)<<1|1]+num[i][k] ) \]

还有就是:

定义局部变量一定要记得初始化啊啊啊啊啊啊!!!

咳 下面是代码:

**code**
/*函数内定义变量一定要初始化啊啊啊啊啊啊*/
#include<bits/stdc++.h>
#define fo(x,y,z) for(int (x)=(y);(x)<=(z);(x)++)
#define fu(x,y,z) for(int (x)=(y);(x)>=(z);(x)--)
using namespace std;
typedef long long ll;
inline int qr()
{
    char ch=getchar();int x=0,f=1;
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*f;
}
#define qr qr()
const int Ratio=0;
const int N=50005;
const int maxx=INT_MAX;
const double eps=1e-8;
int n,m,ans;
#define check(st) ((st&l)||(~st&d))
int num[N][50],zl[N][50];
int main()
{
    // freopen("1.in","r",stdin);
    // freopen("1.out","w",stdout);
    n=qr,m=qr;
    ans=-maxx;
    fo(i,1,m)
    {
        int a=qr,b=qr,c=qr,l=0,r=0,d=0;//***
        fo(j,1,b)
            d=qr,d=(d-a+n)%n,l|=1<<d;
        fo(j,1,c)
            d=qr,d=(d-a+n)%n,r|=1<<d;
        fo(j,0,31)
            if((j&l)||(~j&r))
                num[a][j]++;//第a个点开始状态为j满足的小孩的个数
    }
    fo(i,0,31)//每个人只能看到5动物 枚举状态
    {
        fo(j,0,35)
            zl[0][j]=-maxx;
        zl[0][i]=0;
        fo(j,1,n)//遍历以n为起点向下五个状态的情况
            fo(k,0,31)
                zl[j][k]=max(zl[j-1][(k&15)<<1],zl[j-1][(k&15)<<1|1])+num[j][k];
        ans=max(ans,zl[n][i]);
    }
    printf("%d\n",ans);
    return Ratio;
}

\(End.\)


彩蛋

image

标签:ch,int,题解,APIO2007,动物,啊啊啊,P3622
From: https://www.cnblogs.com/Ratio-Yinyue1007/p/18112391

相关文章

  • 题解:P3903 导弹拦截III
    第一步:确定子任务因为当前拦截的导弹可能在奇数位上,也可能在偶数位上,所以以这两种状态为子任务。第二步:确定状态设$dp[i][0/1]$为作为第(偶数/奇数)个被拦截的导弹,最大可以拦截多少个导弹第三步:推出转移方程$dp[i][0]=max(dp[j][1])+1(1\lej<i且h[i]<h[j])$$dp[i][1]=max(......
  • 题解:P2758 编辑距离
    第一步:确定子问题有4种操作(删除,添加,修改,不变)。所以4个子问题就是操作后的A变为B需要多少步。第二步:确定状态设$dp[i][j]$为将A的前i位变为B的前j位的最小代价。第三步:确定转移方程删除:$dp[i][j]=dp[i-1][j]+1$添加:$dp[i][j]=dp[i][j-1]+1$修改:$dp[i][j]=dp[i-1][j......
  • AGC066 题解
    题解:AT_agc066_a[AGC066A]AdjacentDifference笑点解析:没有必要将总成本最小化。我们将格子间隔的黑白染色(显然有两种染色方法),对于黑点我们要求它是奇数倍\(d\),对于白点我们要求它是偶数倍\(d\),这样一定满足相邻格子相差至少\(d\)。因为两种染色方法的代价和为\(dN^2\),......
  • [ABC259F] Select Edges 题解
    很容易想到树形dp。考虑在有根树内,每个点都有两种状态:不选自己和父亲的边;要选自己和父亲的边。那么单独对于子树内部而言,就要分两种情况:最多可以向\(d_i\)个孩子连边,对应上述第一种情况,我们称之为\(f_i\);最多可以向\(d_i-1\)个孩子连边,对应上述第二种情况,我们称之......
  • ABC347G 题题解
    还算是比较经典了。首先我们注意到一个性质:\(1+3+\cdots+n=n^2\)。所以我们可以把平方拆开。然后容易证明\(a_{i,j}\)填\(1\)一定比填\(0\)不劣。我们可以把\(a_{i,j}\)拆成\(4\)个点,然后我们想到了最小割。构造网络:\(a_{i,j,x}\leftarrowa_{i,......
  • 三道dp的题解报告
    三道dp的题解报告圆题目来源牛客练习赛122D题练习赛链接https://ac.nowcoder.com/acm/contest/75768题面原题面为中文就直接放原题面截图了。解法事实上,把\(n\)与\(1\)断掉,断环为链,把原来的线段看成区间,线段相交就是区间之间部分覆盖(区间有重复部分但是没有相互包含关......
  • 题解:AT_abc176_e [ABC176E] Bomber
    分析我们可以用\(hf\)和\(wf\)分别储存每行的目标数及每列的目标数。然后我们可以贪心:若想摧毁最多的目标,则选定的位置所在的行是所有行中目标最多的,所在的列是所有列中目标最多的(感性理解一下)。但是,选定的位置也可能有一个目标。在统计摧毁的目标数时,该目标被算了两次......
  • P2143 [JSOI2010] 巨额奖金 题解
    P2143[JSOI2010]巨额奖金题解矩阵树定理+Kruskal最小生成树计数。思路MST都是喵喵题。引理1:所有合法的权值相同边的连边方案,得到的连通块情况是相同的。感性理解:如果不相同意味着至少有一条边可以连通一对连通块。所以我们可以这么做:先跑Kruskal标记树边,然后枚举......
  • P1967 [NOIP2013 提高组] 货车运输 题解
    P1967[NOIP2013提高组]货车运输原题地址思路:由于题目要求的是使两点之间的最小边权最大,所以可以构造最大生成树(最大生成树一定是最大瓶颈生成树,而瓶颈生成树上两点之间的路径,在原图中的所有路径中,最小边权仍然最大,即满足题目要求,详见https://oi-wiki.org/graph/mst/#性质),......
  • Golang | Leetcode Golang题解之第4题寻找两个正序数组的中位数
    题目:题解:funcfindMedianSortedArrays(nums1[]int,nums2[]int)float64{iflen(nums1)>len(nums2){returnfindMedianSortedArrays(nums2,nums1)}m,n:=len(nums1),len(nums2)left,right:=0,mmedian1,median2:=0,0......