码迷,mamicode.com
首页 > 其他好文 > 详细

2016-2017 ACM-ICPC Northeastern European Regional Contest (NEERC 16)

时间:2018-07-13 23:46:35      阅读:432      评论:0      收藏:0      [点我收藏+]

标签:alt   closed   img   费用流   str   pre   test   i++   iostream   

D:上下界费用流

将每个点和每个长度D的区间看作边,限制条件看作流量上下界,差分建图,无源汇最大费用费用流,非常巧妙的使用了差分建图。

技术分享图片
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#define N 100003
#define inf 2000000000
#define LL long long
using namespace std;
const LL INF=1e17;
int tot,nxt[N],point[N],v[N],remain[N],can[N],last[N],n,k,t1,t2,a[N],b[N];
LL cost[N],dis[N],ans;
void add(int x,int y,int z,LL k)
{
    tot++; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; remain[tot]=z; cost[tot]=k;
    tot++; nxt[tot]=point[y]; point[y]=tot; v[tot]=x; remain[tot]=0; cost[tot]=-k;
}
int addflow(int s,int t)
{
    int ans=inf; int now=t;
    while (now!=s) {
        ans=min(ans,remain[last[now]]);
        now=v[last[now]^1];
    }
    now=t;
    while (now!=s) {
        remain[last[now]]-=ans;
        remain[last[now]^1]+=ans;
        now=v[last[now]^1];
    }
    return ans;
}
bool spfa(int s,int t)
{
    for (int i=1;i<=t;i++) dis[i]=INF,can[i]=0;;
    dis[s]=0; can[s]=1;
    queue<int> p; p.push(s);
    while (!p.empty()) {
        int now=p.front(); p.pop();
        can[now]=0;
        for (int i=point[now];i!=-1;i=nxt[i])
         if (remain[i]&&dis[v[i]]>dis[now]+cost[i]){
            dis[v[i]]=dis[now]+cost[i];
            last[v[i]]=i;
            if (!can[v[i]]) {
                can[v[i]]=1;
                p.push(v[i]);
             }
         }
    }
    if (dis[t]==INF) return false;
    int flow=addflow(s,t);
    ans+=dis[t];
    return true;
}
int main()
{
    freopen("delight.in","r",stdin);
    freopen("delight.out","w",stdout);
    scanf("%d%d%d%d",&n,&k,&t1,&t2);
    LL sum=0;
    tot=-1;
    memset(point,-1,sizeof(point));
    for (int i=1;i<=n;i++) scanf("%d",&a[i]),sum+=(LL)a[i];
    for (int i=1;i<=n;i++) scanf("%d",&b[i]);
    int mn=t2; int mx=k-t1;
    int S=n+1;  int SS=S+1; int TT=SS+1;
    for (int i=1;i<=n;i++) add(i,i+k>n?TT:i+k,1,-(b[i]-a[i]));
    for (int i=1;i<=n;i++) add(i,i+1>n?TT:i+1,mx-mn,0);
    for (int i=1;i<=k;i++) add(S,i,inf,0);
    add(SS,S,mx,0);
    while (spfa(SS,TT));
    printf("%lld\n",sum-ans);
    for (int i=1;i<=2*n-1;i+=2)
     if (remain[i]) printf("E");
     else printf("S");
    printf("\n");
}
View Code

F:概率DP

设dp[i]表示从i这里切一次,i以及i之后w的期望,很容易看出这是可以DP转移的

若i处是w,dp[i]=1/n*∑(∑(sum_c[i..j])+dp[j])否则是:dp[i]=1/n*∑(∑(sum_w[i..j])+dp[j]),维护一下sum_c和sum_w即可

技术分享图片
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#include <string>
#include <map>
using namespace std;
double sum[1000010],dp[1000010];
char str[1000010];
int n;

int main()
{
    freopen("foreign.in","r",stdin);
    freopen("foreign.out","w",stdout);
    int i;
    scanf("%s",str);
    n=strlen(str);
    for(i=0;i<n;i++)
    {
        if(str[i]==C) sum[i]=1.0;
    }
    for(i=n-1;i>=0;i--) sum[i]+=sum[i+1];
    double sum_c=0.0,sum_w=0.0,cnt=0.0;
    if(str[n-1]==C)sum_c=1.0;
    else sum_w=1.0;
    for(i=n-2;i>=0;i--)
    {

        if(str[i]==C)
        {
            dp[i]=(cnt+sum_w)/(double)(n-i);
            sum_c+=(double)(n-i);
        }
        else
        {
            dp[i]=(cnt+sum_c)/(double)(n-i);
            sum_w+=(double)(n-i);
        }
        //cout<<dp[i]<<endl;
        cnt+=dp[i];
    }
    printf("%.10lf\n",dp[0]);
    //cout<<dp[0]<<endl;
    return 0;
}
View Code

J:物理题

用求重心的公式强行算即可,n^2的复杂度根本不虚

技术分享图片
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#include <string>
#include <map>
const double eps=1e-10;
using namespace std;

struct zx
{
    double x,y;
};

zx zx_all[5010],zx_a[5010];
int n,w,h,m;
int vis[5010][5010];
int num[5010];
double le[5010],ri[5010];

int main()
{
    freopen("jenga.in","ri",stdin);
    freopen("jenga.out","w",stdout);
    int i,j;
    scanf("%d%d%d%d",&n,&w,&h,&m);
    int l,k;
    num[h+1]=0;
    for(i=h;i>=1;i--)
    {
        le[i]=0;
        ri[i]=n*w;
        num[i]=num[i+1]+n;
        zx_all[i].x=zx_a[i].x=(double)(n*w)/2.0;
        zx_all[i].y=zx_a[i].y=(double)(n*w)/2.0;
    }
    int ans=-1;
    for(i=1;i<=m;i++)
    {
        scanf("%d%d",&l,&k);
        if(ans!=-1) continue;
        vis[l][k]=1;
        for(j=l;j>=1;j--)
        {
            num[j]--;
            if(num[j]==num[j+1]||num[h]==0)
            {
                ans=i;
                break;
            }
        }
        if(ans!=-1) continue;
        if(num[l]==num[l+1])
        {
            ans=i;
            break;
        }
        else
        {
            for(j=1;j<=n;j++)
            {
                if(!vis[l][j])
                {
                    le[l]=(double)(j-1)*w;
                    break;
                }
            }
            for(j=n;j>=1;j--)
            {
                if(!vis[l][j])
                {
                    ri[l]=(double)j*w;
                    break;
                }
            }
        }
        double temp=0;
        double tmp=0;
        for(j=1;j<=n;j++)
        {
            if(!vis[l][j])
            {
                temp+=((j-1)*w+w/2);
                tmp+=1.0;
            }
        }
        temp/=tmp;
        if(l%2==1)
        {
            zx_a[l].x=temp;
        }
        else
        {
            zx_a[l].y=temp;
        }
        for(j=l;j>=1;j--)
        {
            zx_all[j].x=(zx_all[j+1].x*num[j+1]+zx_a[j].x*(num[j]-num[j+1]))/num[j];
            zx_all[j].y=(zx_all[j+1].y*num[j+1]+zx_a[j].y*(num[j]-num[j+1]))/num[j];
            if(j!=h&&(j&1)&&((zx_all[j+1].x<=le[j]||zx_all[j+1].x>=ri[j])||(fabs(zx_all[j+1].x-le[j])<eps)||(fabs(zx_all[j+1].x-ri[j])<eps)))
            {
                ans=i;
                break;
            }
            else if(j!=h&&!(j&1)&&((zx_all[j+1].y<=le[j]||zx_all[j+1].y>=ri[j])||(fabs(zx_all[j+1].y-le[j])<eps)||(fabs(zx_all[j+1].y-ri[j])<eps)))
            {
                ans=i;
                break;
            }
        }
    }
    if(ans==-1)
    {
        puts("no");
    }
    else
    {
        puts("yes");
        printf("%d\n",ans);
    }
    return 0;
}
View Code

 

2016-2017 ACM-ICPC Northeastern European Regional Contest (NEERC 16)

标签:alt   closed   img   费用流   str   pre   test   i++   iostream   

原文地址:https://www.cnblogs.com/Hetui/p/9307919.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!