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

内网OJ题解

时间:2015-10-25 16:20:00      阅读:369      评论:0      收藏:0      [点我收藏+]

标签:

OJ1001A+B Problem:

  a+b。

技术分享
#include<bits/stdc++.h>
using namespace std;
int main(){
    int a,b;
    cin>>a>>b;
    cout<<a+b<<endl;
    return 0;
}
my code

OJ1004讲笑话

  用sum[i]记录前缀和为i的位置数量。

  ans=sum[0]+Σsum[i]*(sum[i]-1)/2。

技术分享
#include<cstdio>
#include<iostream>
using namespace std;
int n,sum[2000015];
int main(){
    scanf("%d",&n);int cur=n;
    for (int x,i=1;i<=n;++i){
        scanf("%d",&x);
        ++sum[cur+=x];
    }
    int res=sum[n];
    for (int i=0;i<=2000000;++i) res=(res+1ll*sum[i]*(sum[i]-1)/2)%999999;
    cout<<res<<endl;
    return 0;
}
my code

OJ1006海岛之桥

  最小生成树。

技术分享
var
  ans,i,j,n:longint;
  dis:array[1..100,1..100]of longint;
  bo:array[1..100]of boolean;
procedure mst;
var
  min,mini:longint;
  lowest:array[1..100]of longint;
begin
  for i:=2 to n do
    lowest[i]:=maxlongint;
  lowest[1]:=0;
  while true do
  begin
    min:=maxlongint;
    for i:=1 to n do
    begin
      if (bo[i]) and (lowest[i]<min) then
      begin
        min:=lowest[i];
        mini:=i;
      end;
    end;
    if min=maxlongint then
      break;
    bo[mini]:=false;
    ans:=ans+min;
    for i:=1 to n do
      if (bo[i]) and (dis[mini,i]<lowest[i]) then
        lowest[i]:=dis[mini,i];
  end;
end;

begin
  readln(n);
  for i:=1 to n-1 do
    for j:=i+1 to n do
    begin
      read(dis[i,j]);
      dis[j,i]:=dis[i,j];
    end;
  fillchar(bo,sizeof(bo),true);
  mst;
  writeln(ans);
end.
my code

OJ1007[jsoi2008]星球大战

  离线处理,利用并查集求连通块数,将删点变为加点。

技术分享
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1000010;
int n,m,k,res,tot,v[maxn],in[maxn],fa[maxn],ans[maxn],now[maxn],pre[maxn],son[maxn],des[maxn];
void Connect(int a,int b){
    pre[++tot]=now[a];
    now[a]=tot;
    son[tot]=b;
}
void Init(){
    scanf("%d%d",&n,&m);
    for (int x,y,i=1;i<=m;++i){
        scanf("%d%d",&x,&y);
        Connect(x,y),Connect(y,x);
    }
    scanf("%d",&k);
    for (int i=1;i<=k;++i){
        scanf("%d",&des[i]);
        v[des[i]]=1;
    }
}
int Get(int x){return fa[x]=fa[x]==x?x:Get(fa[x]);}
void Put(int x){
    ++res;
    for (int p=now[x];p;p=pre[p]){
        int y=son[p];
        if (!in[y]) continue;
        int w=Get(y);
        if (x!=w) fa[w]=x,--res;
    }
    in[x]=1;
}
void Work(){
    for (int i=0;i<n;++i) fa[i]=i;
    for (int i=0;i<n;++i) if (!v[i]) Put(i);
    ans[k+1]=res;
    for (int i=k;i>=1;--i) Put(des[i]),ans[i]=res;
    for (int i=1;i<=k+1;++i) printf("%d\n",ans[i]);
}
int main(){
    Init();
    Work();
    return 0;
}
my code

OJ1009剑圣的逃跑

  f[i][j][k]代表当前在(i,j)已使用k次疾风步的最小伤害。

技术分享
var
  i,ci,j,k,m,n,q,minn,t:longint;
  a:array[0..202,0..404]of longint;
  f:array[0..202,0..404,0..202]of integer;

function min(a,b:longint):longint;
begin
  if a>=b then min:=b
  else min:=a;
end;

begin
  readln(n,q);
  readln(m);
  for i:=1 to n do
    begin
      for j:=1 to i*2-1 do
        read(a[i,j]);
      readln;
    end;
  fillchar(f,sizeof(f),$7f);
  f[1,1,1]:=0;
  f[1,1,0]:=a[1,1];
  for i:=1 to n-1 do
    for j:=1 to i*2-1 do
      for k:=0 to q do
        for t:=0 to 2 do
          f[i+1,j+t,k]:=min(min(f[i+1,j+t,k],f[i,j,k-1]),f[i,j,k]+a[i+1,j+t]);
  minn:=maxlongint;
  for i:=1 to n*2-1 do
    if f[n,i,q]<minn then
        minn:=f[n,i,q];
  if minn>=m then
     writeln(DEAD)
  else
     writeln(m-minn);
end.
my code

OJ1011选数

  差分约束系统。可以参照:http://ycool.com/post/m2uybbf

技术分享
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
/*
    令sum[i]代表i及之前选了多少个点
    对于条件(a,b,c),即可化为
        sum[b]-sum[a-1]>=c
    还存在条件
        sum[i]-sum[i-1]>=0
        sum[i]>=0 
    转化为 sum[b]>=c+sum[a-1].
    比较最长路三角不等式,dis[b]>=dis[a-1]+w(a-1,b)。
    于是可以令0点dis=0,并连接0和每个i,边权为0
    对于条件(a,b,c),连边(a-1,b,c)。
    做最长路即可。 
*/
const int maxn=100015,maxm=500015;
int n,tot,now[maxn],pre[maxm],son[maxm],val[maxm];
void connect(int u,int v,int w){pre[++tot]=now[u];now[u]=tot;son[tot]=v;val[tot]=w;}
void init(){
    scanf("%d",&n);
    for (int u,v,w,i=1;i<=n;++i){
        scanf("%d%d%d",&u,&v,&w);
        ++u;++v;
        connect(u-1,v,w);
    }
    for (int i=1;i<=50001;++i){
        connect(0,i,0);
        connect(i,i+1,0);
        connect(i,i-1,-1); 
    }
}
/*
    wa了 好像漏了一个条件
    sum[i]-sum[i-1]<=1
    即sum[i-1]-sum[i]>=-1
    即dis[i-1]>=dis[i]-1
    连接(i,i-1,-1)。 
*/
bool inq[maxn];
int head,tail,q[maxn],dis[maxn];
void spfa(int s){
    memset(dis,200,sizeof(dis));
    dis[s]=0;q[1]=s;head=0;tail=1;inq[s]=1;
    while (head!=tail){
        if (++head==maxn) head=1;
        int u=q[head];
        for (int p=now[u];p;p=pre[p])
            if (dis[son[p]]<dis[u]+val[p]){
                dis[son[p]]=dis[u]+val[p];
                if (!inq[son[p]]){
                    if (++tail==maxn) tail=1;
                    q[tail]=son[p];inq[son[p]]=1;
                }
            }
        inq[u]=0;
    }
}
void work(){
    spfa(0);
    printf("%d\n",dis[50002]);
}
int main(){
    freopen("data11.in","r",stdin);
    init();
    work();
    return 0;
}
my code

OJ1012酒鬼

  DP。f[i][j]代表当前做到前i瓶,上一个没喝的瓶在i-j。

  f[i][0]=max(f[i-1][0],f[i-1][1],f[i-1][2])。

  f[i][1]=f[i-1][0]+v[i]。

  f[i][2]=f[i-1][1]+v[i]。

  ans=max(f[n][0],f[n][1],f[n][2])。

技术分享
var
    f:array[0..1000,0..2] of longint;
    i,v:longint;
function max(a,b,c:longint):longint;
begin
    if a>b then max:=a
    else max:=b;
    if c>max then max:=c;
end;
begin
    readln(i);
    for i:=1 to i do
    begin
        readln(v);
        f[i,0]:=max(f[i-1,0],f[i-1,1],f[i-1,2]);
        f[i,1]:=f[i-1,0]+v;
        f[i,2]:=f[i-1,1]+v;
    end;
    writeln(max(f[i,0],f[i,1],f[i,2]));
end.
my code

待更新。

内网OJ题解

标签:

原文地址:http://www.cnblogs.com/iamCYY/p/4908888.html

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