炸的票房价值一样。使得选出的物品的重量的中位数最要命。  用到一个物。

迎访问~原文出处——博客园-zhouzhendong

题目:

接访问~原文出处——博客园-zhouzhendong

去博客园看该题解


1. 中位数

去博客园看该题解


问题传送门 – 洛谷2973


【问题讲述】

题目传送门 – BZOJ1076


题意概括

  有N个城市,M条双向道路组成的地形图,城市标号为1至N。“西瓜炸弹”放在1如泣如诉都市,保证城市1足足连接在一个外城市。“西瓜炸弹”有P/Q的票房价值会放炮,每次上其他城市经常,爆炸的几率一样。如果它们并未爆炸,它见面自由的选取一样长达道及其它一个市去,对于当前都会所连接的各级一样长条道都发平等的可能性被入选。对于给定的地形图,求每个市“西瓜炸弹”爆炸的票房价值。


于定C个不同物品,每个物品有一致分量与体积,保证每个物品的重不等同。从中选出N个物品,在体积不超F的状况下,使得选出的品的份量的中位数最充分。所谓中位数,就是排序后处于最中间的分量,比如3,8,9,7,5底中位数是7。

题意概括

  有n个东西,k次扔出来。每次等概率扔来中一个。

  你得将这东西,但是来标准,得在以到指定东西之后还以,否则白拿。

  用到一个东西,会拿走该权值。可以是负数。


 

题解

  通过概率关系构建方程:

  其中in[j]代表节点j的出度。

  图片 1

  然后高斯消元跑同一挥发就足以了。


【输入格式】

题解

  状压dp跑一发。

  同开始思念写正着dp的,因为自认为这么放生爱想的。

  然而网上的大牛都说凡是反在的。于是我倒着了。

  方程是这样的:

  dp[i][j]意味着扔出来i次后,状态也j,在马上事后可以获得的无限要命收益。

  dp[i][j]=(∑F[k])/n

  F[k]划分点儿种植情形。如果在状态j的事态下得以取k,那么F[k]
= max(dp[i+1][j],dp[i+1][j | (1<<k)] + v[k])

    否则F[k] = dp[i+1][j]

  根据意义,最后输出dp[0][0]即可。


 

代码

#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;
const int N=300+5;
const double Eps=1e-9;
int n,m,P,Q,cnt[N];
bool g[N][N];
double p,a[N][N],x[N];
void Gauss(){
    int row=n,col=n,k,c;
    for (k=c=1;k<=row,c<=col;k++,c++){
        int Mk=k;
        for (int i=k+1;i<=row;i++)
            if (fabs(a[Mk][c])<fabs(a[i][c]))
                Mk=i;
        if (fabs(a[Mk][c])<Eps){
            k--;
            continue;
        }
        if (k!=Mk)
            for (int i=c;i<=col+1;i++)
                swap(a[k][i],a[Mk][i]);
        for (int i=k+1;i<=row;i++)
            for (int j=col+1;j>=c;j--)
                a[i][j]=a[i][j]-a[k][j]*a[i][c]/a[k][c];
    }
    memset(x,0,sizeof x);
    for (int i=k;i>=1;i--){
        x[i]=a[i][n+1];
        for (int j=i+1;j<=n;j++)
            x[i]-=a[i][j]*x[j];
        x[i]/=a[i][i];
    }
}
int main(){
    scanf("%d%d%d%d",&n,&m,&P,&Q);
    p=double(P)/double(Q);
    memset(g,0,sizeof g);
    memset(cnt,0,sizeof cnt);
    for (int i=1,a,b;i<=m;i++){
        scanf("%d%d",&a,&b);
        g[a][b]=g[b][a]=1;
        cnt[a]++,cnt[b]++;
    }
    memset(a,0,sizeof a);
    a[1][n+1]=p;
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++){
            if (i==j){
                a[i][j]=1;
                continue;
            }
            if (!g[i][j])
                continue;
            double del=(1.0-p)/double(cnt[j]);
            a[i][j]-=del;
        }
    Gauss();
    for (int i=1;i<=n;i++)
        if (fabs(x[i])<Eps)
            x[i]=0;
    for (int i=1;i<=n;i++)
        printf("%.9lf\n",x[i]);
    return 0;
}

  

第一实行:三个用空格分开的平头:N,C和F。1 ≤ N ≤ 19999,N ≤ C ≤ 105

代码

#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
using namespace std;
const int N=15+5,M=100+5,S=(1<<15)+5;
int n,m,v[N],pre[N];
double dp[M][S];
int main(){
    scanf("%d%d",&m,&n);
    memset(pre,0,sizeof pre);
    for (int i=0,p;i<n;i++){
        scanf("%d",&v[i]);
        while (scanf("%d",&p)&&p!=0)
            pre[i]|=1<<(p-1);
    }
    for (int i=m-1;i>=0;i--)
        for (int j=0;j<(1<<n);j++){
            dp[i][j]=0;
            for (int k=0;k<n;k++)
                if ((pre[k]&j)==pre[k])
                    dp[i][j]+=max(dp[i+1][j],dp[i+1][j|(1<<k)]+v[k]);
                else
                    dp[i][j]+=dp[i+1][j];
            dp[i][j]/=n;
        }
    printf("%.6lf",dp[0][0]);
    return 0;
}

 

,0 ≤ F ≤ 2 × 109

仲实施及C + 1行:每行有有限个用空格分开的整数。第一个数是这物品的份量Wi,第二只数是此物品的体积Qi。

【输出格式】

首先推行:一个平头,表示可以获取的最为酷中位数,如果F装不生任何N个物品,则输出-1。

【输入样例】

3 5 70

30 25

50 21

20 20

5 18

35 30

【输出样例】

35

【样例解释】

分选重量也 5, 35, 50 的品,中位数为 35,体积18 + 30 + 21 = 69,小于70。

【数据范围】

    40%的数据,1 ≤ N≤ C ≤200

100%的数据,1 ≤ N ≤ 19999,N ≤ C ≤ 105,0 ≤ F ≤ 2 × 109,0 ≤ Qi≤ 105,0 ≤ Wi≤ 2 × 109。保证n为奇数。

 

 

2. 爆炸

【问题讲述】

 有N个城市,M条双向道路组成的地形图,城市标号为1到N。“西瓜炸弹”放在1声泪俱下都,保证城市1足足连接着一个其他城市。“西瓜炸弹”有P/Q的票房价值会放炮,每次上外城市经常,爆炸的概率一样。如果它们并未爆炸,它见面随机的挑选一样长条道及其他一个都会去,对于当前都会所连接的各国一样漫漫道都发出雷同之可能性被入选。对于给定的地形图,求每个市“西瓜炸弹”爆炸的票房价值。

如,假要单独来一定量只市1与2,它们被同长道路连接起来。最开始“西瓜炸弹”放在城市1,每次上都它还发出1/2底可能性爆炸: 

1 — 2

俺们就是时有发生以下可能的门道(其中最后一件是收城市,即“西瓜炸弹”爆炸并传该城市): 

1: 1 
2: 1-2 
3: 1-2-1 
4: 1-2-1-2 
5: 1-2-1-2-1 
etc. 

为探寻有“西瓜炸弹”在城市1爆裂的可能性,我们得以管第1、3、5…种途径出现的票房价值加起来(在斯事例中就把具备奇数路径出现的可能性加起来)。 
对第k种途径出现的可能性为(1/2)^k:在通过前k-1次时,炸弹绝对不见面在都会1爆裂(每一样浅的票房价值为1 – 1/2 = 1/2),然后最后在城市1炸(概率也1/2)。 

据此,在都1放炮的可能性就是 1/2 + (1/2)^3 + (1/2)^5 + … ,把这些往往还加以起就等于2 / 3,约为0.666666667。 
因而在市2爆炸的可能性就是1/3,约为0.333333333。

【输入格式】

第1实行:四个给空格分隔整数:N,M,P和Q 

第2..M+1行:第i执行描述了一定量独空格分隔的整数:A_j 和 B_j(表示都A_j与B_j相连)

【输出格式】

第1..N行:第i行事一个小数,表示第i独都 “西瓜炸弹”爆炸的概率。至少要规范到10^-6才有效。

【输入样例1】

2 1 1 2 
1 2

【输出样例1】

0.666666667 
0.333333333

【输入样例2】

3 2 1 3

1 2

3 2

【输出样例2】

0.466666667

0.400000000

0.133333333

【数据范围】

20%  2<=N<=25 , 1<=M<=100

100% 2 <= N <= 300 ,1 <= M <= 44850 ,1 <= P <= 1,000,000,1 <= Q <= 1,000,000

 

3.队划分

 

【题目叙述】

给得一个队列{An},现在,需要把这班划分成K个子序列,使得每个子序列包含的多次之个数不少于2,并且要非升,要么非降。你的天职就是求出K的卓绝小值。

 

【输入文件】

输入第一实践一个正要整数N,表示序列长度,接下N行,第i执代表元素Ai-1

 

【输出文件】

假定未可知分是队列,输出一个数0;否则输出K。

 

【样例输入1】

6

12

33

97

18

15

33

 

【样例输出1】

2

【样例输入2】

1

88

【样例输出2】

0

【样例输入3】

4

77

22

22

11

【样例输出3】

1

【数据规模】

对于30%的数据,1<=N<=10;

对于100%的数据,1<=N<=25,1<=Ai<=100;

 

 题解:

相同:按照体积排序

1.预拍卖前i小、大之体积的品的分量拿n/2单底极度小重量

下一场一个个枚举过去,看看是不是建

有关预处理便因故一个堆好了

第二:高斯消元+概率dp

本想使简单的dp+收敛,没有想到数据那么坑。。。

(其实照自由的票房价值大概可以过p/q>0.02的情状吧)

正解:高斯校园+概率

排有n个方程,解n个数字,就是高斯消元

其三:迭代深搜

枚举有微微个可,然后按照类似与导弹拦截的贪方法做贪心

代码:

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=200005;
int f[N],d[N],l,a[N],b[N],n,m,F;
long long f1[N],f2[N];
void up(int x)
{
    if (x==1)return;
    if (d[x]>d[x/2])
     {
         swap(d[x],d[x/2]);
         up(x/2);
     }
}
void down(int x)
{
    int i=x;
    if (x*2<=l&&d[x]<d[x*2])i=x*2;
    if (x*2<l&&d[i]<d[x*2+1])i=x*2+1;
    if (i!=x)
     {
         swap(d[x],d[i]);
         down(i);
     }
}
int cmp(int x,int y)
{
    return a[x]<a[y];
}
int main()
{
    freopen("finance.in","r",stdin);
    freopen("finance.out","w",stdout); 
    scanf("%d%d%d",&n,&m,&F);
    for (int i=1;i<=m;i++)scanf("%d%d",&a[i],&b[i]),f[i]=i;
    sort(f+1,f+m+1,cmp);
    for (int i=1;i<=n/2;i++)d[i]=b[f[i]],f1[i]=f1[i-1]+b[f[i]];
    l=n/2;
    for (int i=1;i<=n/2;i++)up(i);
    for (int i=n/2+1;i<=m;i++)
     {
         if (b[f[i]]>=d[1])
          {
              f1[i]=f1[i-1];
              continue;
          }
         f1[i]=f1[i-1]+b[f[i]]-d[1]; 
         d[1]=b[f[i]];
        down(1); 
     }
    memset(d,0,sizeof d);
    for (int i=m;i>m-n/2;i--)d[m-i+1]=b[f[i]],f2[i]=f2[i+1]+b[f[i]];
    for (int i=1;i<=n/2;i++)up(i);    
    for (int i=m-n/2;i;i--)
     {
         if (b[f[i]]>=d[1])
          {
              f2[i]=f2[i+1];
              continue;
          }
         f2[i]=f2[i+1]+b[f[i]]-d[1]; 
         d[1]=b[f[i]];
        down(1);          
     }  
    for (int i=m-n/2;i>n/2;i--)
     if (F>=f1[i-1]+f2[i+1]+b[f[i]])
      {
          printf("%d",a[f[i]]);
          return 0;
      }
    puts("-1");
    return 0;  
} 

#include <bits/stdc++.h>
using namespace std;
typedef double ld;
const int N=305;
const ld eps=1e-15;
int n,m,mp[N][N],du[N];
ld f[N][N],sum,P,Q;
int main()
{
    freopen("dotp.in","r",stdin);
    freopen("dotp.out","w",stdout);
    scanf("%d%d%lf%lf",&n,&m,&P,&Q);
    for(int i=1,x,y;i<=m;i++)
     {
        scanf("%d%d",&x,&y);
        mp[x][y]++;mp[y][x]++;
        du[x]++;du[y]++;
     }
    f[1][n+1]=1;
    for(int i=1;i<=n;i++)
     {
        f[i][i]=1;
        for(int j=1;j<=n;j++)
         if(mp[i][j])f[i][j]+=((ld)P/Q-1)/du[j]*mp[i][j];
     }
    for(int i=1;i<=n;i++)
     {
        int t=i;
        for(int j=i;j<=n;j++)
         if(fabs(f[j][i])>eps)t=j;
        for(int j=1;j<=n+1;j++)swap(f[i][j],f[t][j]);
        for(int j=1;j<=n;j++)
         if(j!=i&&fabs(f[j][i])>eps)
          {
            ld t=f[j][i]/f[i][i];
            for(int k=1;k<=n+1;k++)f[j][k]-=f[i][k]*t;
          }
     }
    for(int i=1;i<=n;i++)sum+=(f[i][i]=f[i][n+1]/f[i][i]);
    for(int i=1;i<=n;i++)printf("%.9lf\n",(double)(f[i][i]/sum+eps));
    return 0;
}

#include<bits/stdc++.h>
using namespace std;
const int N=30;
int a[N][N],b[N][N],A,B,ans[N],x[N],dep,n;
void DFS(int u)
{
    if (A+B>dep)return;
    if (u>n)
     {
        for (int i=1;i<=A;i++)
         if (*a[i]<2)return;
        for (int i=1;i<=B;i++)
         if (*b[i]<2)return;
        printf("%d\n",dep);
        exit(0);
     }
    int v=0;
    for (int i=1;i<=A;i++)
     if (a[i][*a[i]]<=x[u]&&(!v||a[v][*a[v]]<a[i][*a[i]]))v=i;
    if (!v)
     {
        ++A;
        a[A][++*a[A]]=x[u];
        ans[u]=A;
        DFS(u+1);
        --*a[A--];
     }
    else
     {
        a[v][++*a[v]]=x[u];
        ans[u]=v;
        DFS(u+1);
        --*a[v];
     }
    v=0;
    for (int i=1;i<=B;i++)
     if (b[i][*b[i]]>=x[u]&&(!v||b[v][*b[v]]>b[i][*b[i]]))v=i;
    if (!v)
     {
        ++B;
        b[B][++*b[B]]=x[u];
        ans[u]=dep+1-B;
        DFS(u+1);
        --*b[B--];
     }
    else
     {
        b[v][++*b[v]]=x[u];
        ans[u]=dep+1-v;
        DFS(u+1);
        --*b[v];
     }
}
int main()
{
    freopen("sequence.in","r",stdin);
    freopen("sequence.out","w",stdout);
    scanf("%d",&n);
    for (int i=1;i<=n;i++)scanf("%d",&x[i]);
    for (dep=1;dep*2<=n;dep++)
      {
        memset(a,0,sizeof a);
        memset(b,0,sizeof b);
        A=B=0;
        DFS(1);
     }
    puts("0");    
    return 0;
}

 

相关文章