zoukankan      html  css  js  c++  java
  • [CSP-S模拟测试]:题(DP)

    题目描述

    由于出题人赶时间所以没办法编故事来作为背景。
    一开始有$n$个苹果,$m$个人依次来吃苹果,第$i$个人会尝试吃$u_i$或$v_i$号苹果,具体来说分三种情况。
    $ullet 1.$两个苹果都还在,那么这个人将随便选一个苹果吃了。
    $ullet 2.$只有一个苹果,那么这个人将吃掉这个苹果。
    $ullet 3.$都不在了,这个人吃不到苹果就走了。
    请问有多少对苹果$(i,j)(i<j)$满足它们两个都幸存下来的概率$>0$。


    输入格式

    第一行两个数$n,m$。
    接下来$m$行,每行两个数$u_i,v_i$。


    输出格式

    一个数表示答案。


    样例

    样例输入:

    4 3
    1 2
    3 4
    2 3

    样例输出:

    1


    数据范围与提示

    样例解释:

    只有$(1,4)$满足条件。

    数据范围:

    对于测试点$1sim 5$:$n,mleqslant 20$。
    对于测试点$5sim 8$:若把苹果看做点,人看做边,那么会形成一棵树。
    对于测试点$9sim 15$:$mleqslant 400$。
    对于测试点$16sim 25$:无特殊限制。
    对于所有的数据,$nleqslant 400,mleqslant 5 imes 10^4$。


    题解

    考虑一个类似$DP$的做法,定义$f_k(S)$表示$k$个人来过之后,$S$集合的苹果是否都还没有被吃的概率,那么我们可以列出状态转移方程:

    $alpha.u_i,v_iin S,f_k(S)=0$,都在这个集合肯定不行,因为这两个苹果不能共同存活。

    $eta.u_iin S,f_k(S)=f_{k-1}(Scup{u_i})$,相当与上一次可以有它,但是这一次就不能有了。

    $gamma.v_iin S,f_k(S)=f_{k-1}(Scup{v_i})$,同上。

    $delta.u_i,v_i otin S,f_k(S)=f_{k-1}(S)$,如果都不在,肯定没问题。

    但是我们最后可能会得到好多的集合,选最小的一个?

    肯定不行,那么我们考虑在转化一下思路。

    逆着推,那么状态转移方程就变成了:

    $alpha.u_i,v_iin S$,推不动了。

    $eta.u_iin S,f_k(Scup{u_i})=f_{k+1}(S)$。

    $gamma.v_iin S,f_k(Scup{v_i})=f_{k+1}()S$。

    $delta.u_i,v_i otin S,f_k(S)=f_{k+1}(S)$。

    初始值$f_m(i)=1$。

    时间复杂度:$Theta(n imes n+n^2)$。

    期望得分:$100$分。

    实际得分:$100$分。


    代码时刻

    #include<bits/stdc++.h>
    using namespace std;
    int n,m;
    bool vis[401];
    pair<int,int> e[50001];
    bool bit[401][401];
    int ans;
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;i++)
    		scanf("%d%d",&e[i].first,&e[i].second);
    	for(int i=1;i<=n;i++)
    	{
    		bit[i][i]=1;
    		for(int j=m;j;j--)
    		{
    			if(bit[i][e[j].first]&&bit[i][e[j].second])vis[i]=1;
    			if(bit[i][e[j].first]||bit[i][e[j].second])bit[i][e[j].first]=bit[i][e[j].second]=1;
    		}
    	}
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=n;j++)
    		{
    			for(int k=1;k<=n;k++)
    				if(vis[i]||vis[j]||bit[i][k]&&bit[j][k])goto nxt;
    			ans++;
    			nxt:;
    		}
    	printf("%d",ans>>1);
    	return 0;
    }
    

    rp++

  • 相关阅读:
    圈水池 nyoj 78 凸包算法
    凸包算法入门
    nyoj 633 幂
    软件下载地址
    概率论与数理统计
    迷宫最短路径 问题
    将项目发布至开发环境测试环境的方法
    一些JavaScript技巧
    随机生成10个不重复的0-100的数字
    Git添加远程库和从远程库中获取(新手傻瓜式教学)
  • 原文地址:https://www.cnblogs.com/wzc521/p/11615972.html
Copyright © 2011-2022 走看看