1. 程式人生 > >紀念一次炸。。

紀念一次炸。。

seve pan 制造 最優 表示 wid 枚舉 題解 int

題目:

1.SEVERINA

【題目描述】

告訴一個文本串和N個模式串,要求文本串由若幹可以重復的模式串首尾相接而成的方案數模1 337 377。

【輸入格式】

第一行為文本串。

第二行為一個整數N,表示有N個模式串。以下N行,每行一個模式串,任意兩個模式串不相同,且不存在其它任何字符。文本串和模式串都是小寫字母。

【輸出格式】

方案數模1337377

【輸入樣例1

abcd

4

a

b

cd

ab

【輸出樣例1

2

【輸入樣例2

afrikapaprika

4

afr

ika

pap

r

【輸出樣例2

1

【輸入樣例3

ababababababababababababababababababababab

3

a

b

ab

【輸出樣例3

759775

【數據範圍】

1<=N<=4 000,文本串長不超過300 000,模式串長不超過100。

2.組裝

【題目描述】

數軸上有m個生產車間可以生產零件。一共有n種零件,編號為1~n。第i個車間的坐標為xi,生產第pi種零件(1<=pi<=n)。你需要在數軸上的某個位置修建一個組裝車間,把這些零件組裝起來。為了節約運輸成本,你需要最小化cost(1)+cost(2)+…+cost(n),其中cost(x)表示生產第x種零件的車間中,到組裝車間距離的平方的最小值。

【輸入格式】

輸入第一行為兩個整數n, m,即零件的種類數和生產車間的個數。以下m

行每行兩個整數xipi1<=pi<=n)。輸入按照生產車間從左到右的順序排列(即xi<=xi+1。註意車間位置可以重復)。輸入保證每種零件都有車間生產。

【輸出格式】

輸出僅一行,即組裝車間的最優位置(可以和某個生產車間重合),四舍五入保留四位小數。輸入保證最優位置惟一。

【輸入輸出樣例】

assemble.in

assemble.out

3 5

-1 3

0 1

2 3

4 2

5 2

2.0000

assemble.in

assemble.out

4 8

-10 2

-8 1

-5 1

-1 3

3 4

4 3

6 2

9 4

0.7500

【數據範圍】

編號

1-4

5-10

n

<=15

<=10000

m

<=25

<=100000

xi

<=100

<=100,000

3.探險

【題目描述】

牙神率領一支探險隊乘坐從倍喜那裏借來的銀色面包車去鄉下探險。

不幸的是,面包車的油箱撞上地上的石頭後漏了,現在他們開一單位長度需要消耗一單位油(原本的消耗加上漏的等於一單位),他們只能停了下來做打算。

他們決定走直線公路去最近的城鎮修車。目前他們還剩P單位油,從他們所在的地方到城市的距離為L單位長度,直線公路上有N個小型加油站,每個地方有Wi的油可以加。由於加油很慢,他們又很心急,所以牙神下令讓你幫忙計算一個加油次數最少的並且能到城市的停站方案。

註意:沒有油的時候就不能繼續前行了。

【輸入文件】

第一行一個整數N。

接下來N行,每行兩個整數Di,Wi,表示這個加油站到城鎮的距離和油量。

第N+2行兩個整數L,P。

【輸出文件】

僅一行,表示答案,如果不能到達,那麽輸出”-1”

【樣例輸入】

4

4 4

5 2

15 10

11 5

25 10

【樣例輸出】

2

【樣例解釋】

開10單位長度恰好到達3號站得到10單位油,然後再開4公裏得到4號站的5單位油,然後直接開到城鎮即可。

【數據規模】

對於100%的數據 N<=10000,Wi<=100,Di<=L<=1000000,P<=1000000

題解:

t1:首先考慮暴力dp,f[i]表示前i位匹配數,很顯然是n^2L的算法

可以用hash優化dp,復雜度降為nl

最後:字母樹

字母樹優化至o(L)

代碼:

#include<bits/stdc++.h>
using namespace std;
const int N=1000005;
char str[105],z[N],c;
int n,m,top=1,ans1,flag[N];
struct node
{
    int ne[26],sum;
}f[N];
void newone(int a)
{
    memset(f[a].ne,-1,sizeof(f[a].ne));
    f[a].sum=0;
}
void build(char str[])
{
    int p=0;
    for (int i=0;str[i];i++)
     {
        int x=str[i]-a;
        if (f[p].ne[x]==-1)
         {
            f[p].ne[x]=top;
            newone(top);
            top++;
         }
        p=f[p].ne[x];
     }   
    f[p].sum++;
}
int ans(int x,int add)
{
    int p=0,int1;
    for (int i=0;i<1000;i++)
     {
        int1=z[x]-a;
        p=f[p].ne[int1];
        if (p==-1) return 0;
        if (f[p].sum>0) 
         {
            flag[x]+=add;
            flag[x]=flag[x]%1337377;
         }
        x++;
     }
    return f[p].sum;
}
int main()
{
    freopen("severina.in","r",stdin);
    freopen("severina.out","w",stdout);
    scanf("%s",z+1); 
    scanf("%d",&m); 
    newone(0);
    for (int i=1;i<=m;i++)
     {
        scanf("%s",&str);
        build(str);
     }
    n=strlen(z+1);
    flag[0]=1;
    for (int i=0;i<=n;i++)
     {
        flag[i]=flag[i]%1337377;
        if (flag[i]>0)ans(i+1,flag[i]);
     }
    printf("%d",flag[n]);
    return 0;
}

t2:本卷中最難的一題。

考慮暴力枚舉每一種零件由哪一些機器制造,時間復雜度:o(c1c2c3...cm)

優化:

每一種機器先由第一個制造,在一個個往後移動

具體看

http://www.cnblogs.com/jianglangcaijin/p/4204478.html

代碼:

#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
const int N=100005;
double aa,bb,ans,fmin,x[N],y;
int c[N],r[N],count1[N],n,m,n1;
struct xx
{
    double num;
    int next;
}z[N];
bool cmp(xx a,xx b)
{
    return a.num<b.num;
}
int read()
{
    int x=0;char ch=getchar();
    bool zositive=1;
    for (;!isdigit(ch);ch=getchar())
     if (ch==-)zositive=0;
    for (;isdigit(ch);ch=getchar())x=x*10+ch-0;
    return zositive?x:-x;
}
int main()
{
    freopen("assemble.in","r",stdin);
    freopen("assemble.out","w",stdout);
    n=read();m=read();
    for(int i=1;i<=m;i++)
     {
        x[i]=read();c[i]=read();
        if(!r[c[i]]) 
         {
            aa+=x[i];
            bb+=x[i]*x[i];
         }
        else    
         {
            count1[i]=r[c[i]];
            z[++n1].num=(x[i]+x[r[c[i]]])/2;
            z[n1].next=i;
         }
        r[c[i]]=i;
     }
    sort(z+1,z+n1+1,cmp);
    ans=y=aa/n;
    fmin=bb-2*aa*y+y*y*n;
    for(int i=1;i<=n1;i++)
     {
        bb-=x[count1[z[i].next]]*x[count1[z[i].next]];
        aa-=x[count1[z[i].next]];
        bb+=x[z[i].next]*x[z[i].next];
        aa+=x[z[i].next];
        y=aa/n;
        if (fmin>bb-2*aa*y+y*y*n) 
         {
            fmin=bb-2*aa*y+y*y*n;
            ans=y;
         }
     }
    printf("%.4lf",ans);
    return 0;
}

t3:堆優化,其實o(n^2)大暴力也可以

註意是到終點的距離

代碼:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=100005;
int f[N],ff[N],p,l,n,a[N],b[N];
void up(int x)
{
    if (x==1)return;
    if (f[x]>f[x/2])
     {
         swap(f[x],f[x/2]);
         up(x/2);
     }
}
void down(int x)
{
    int i=x;
    if (x*2<=l&&f[i]<f[x*2])i=x*2;
    if (x*2<l&&f[i]<f[x*2+1])i=x*2+1;
    if (i!=x)
     {
         swap(f[i],f[x]);
         down(i);
     }
}
int cmp(int x,int y)
{
    return a[x]<a[y];
}
int main()
{
    freopen("exp.in","r",stdin);
    freopen("exp.out","w",stdout);
    scanf("%d",&n);
    for (int i=1;i<=n;i++)scanf("%d%d",&a[i],&b[i]);
    scanf("%d%d",&a[n+1],&p);
    for (int i=1;i<=n;i++)a[i]=a[n+1]-a[i];    
    for (int i=1;i<=n;i++)ff[i]=i;
    sort(ff+1,ff+n+1,cmp); 
    ff[n+1]=n+1;
    n++;
    int q=p,ans=0;
    for (int i=1;i<=n;i++)
     {
         q=q-a[ff[i]]+a[ff[i-1]];
         while (q<0)
          {
              ans++;
              if (ans==i)
               {
                   puts("-1");
                   return 0;
               }
              q+=f[1];
              f[1]=f[l--];
              down(1);
          }
         f[++l]=b[ff[i]];
         up(l);
     } 
    printf("%d",ans); 
    return 0; 
} 

紀念一次炸。。