1. 程式人生 > >9-7測試總結

9-7測試總結

problems return 進行 soft 利用 clear 需要 小寫 結果

玩具謎題

時間限制: 1 Sec 內存限制: 512 MB
提交: 52 解決: 37
[提交][狀態][討論版]

題目描述

小南有一套可愛的玩具小人,它們各有不同的職業。

有一天,這些玩具小人把小南的眼鏡藏了起來。小南發現玩具小人們圍成了一個圈,它們有的面朝圈內,有的面朝圈外。如下圖: 技術分享 這時singer告訴小南一個謎題:“眼鏡藏在我左數第3個玩具小人的右數第1個玩具小人的左數第2個玩具小人那裏。” 小南發現,這個謎題中玩具小人的朝向非常關鍵,因為朝內和朝外的玩具小人的左右方向是相反的:面朝圈內的玩具小人,它的左邊是順時針方向,右邊是逆時針方向;而面向圈外的玩具小人,它的左邊是逆時針方向,右邊是順時針方向。 小南一邊艱難地辨認著玩具小人,一邊數著: “singer朝內,左數第3個是archer。 “archer朝外,右數第1個是thinker。 “thinker朝外,左數第2個是writer。 “所以眼鏡藏在writer這裏!” 雖然成功找回了眼鏡,但小南並沒有放心。如果下次有更多的玩具小人藏他的眼鏡,或是謎題的長度更長,他可能就無法找到眼鏡了。所以小南希望你寫程序幫他解決類似的謎題。這樣的謎題具體可以描述為: 有n
個玩具小人圍成一圈,己知它們的職業和朝向。現在第1個玩具小人告訴小南一個包含m條指令的謎題,其中第i條指令形如“左數/右數第si個玩具小人”。你需要輸出依次數完這些指令後,到達的玩具小人的職業。

輸入

輸入的第一行包含兩個正整數n,m,表示玩具小人的個數和指令的條數。

接下來n行,每行包含一個整數和一個字符串,以逆時針為順序給出每個玩具小人的朝向和職業。其中0表示朝向圈內,1表示朝向圈外。保證不會出現其他的數。字符串長度不超過10且僅由小寫字母構成,字符串不為空,並且字符串兩兩不同。整數和字符串之間用一個空格隔開。

接下來m行,其中第i
行包含兩個整數ai,si,表示第i條指令。若ai=0,表示向左數si個人;若ai=1,表示向右數si個人。保證ai不會出現其他的數,1≤si<n

輸出

輸出一個字符串,表示從第一個讀入的小人開始,依次數完m條指令後到達的小人的職業。

樣例輸入

7 3
0 singer
0 reader
0 mengbier
1 thinker
1 archer
0 writer
1 mogician
0 3
1 1
0 2

10 10
1 c
0 r
0 p
1 d
1 e
1 m
1 t
1 y
1 u
0 v
1 7
1 1
1 4
0 5
0 3
0 1
1 6
1 2
0 8
0 4

樣例輸出

writer


y

提示


【樣例 1 說明】
這組數據就是【題目描述】中提到的例子。





【子任務】
子任務會給出部分測試數據的特點。如果你在解決題目中遇到了困難,可以嘗試只解決一部分測試數據。
每個測試點的數據規模及特點如下表: 暴力枚舉啦,有個註意點就是a+=b%=c的話貌似先執行%操作
#include<iostream> 
#include<cstdio> 
#include<algorithm> 
#include<map> 
using namespace std; 
map<int,string> Map; 
char str[1005],Mode[100005]; 
int n,m,val,dir; 
int main() 
{ 
    scanf("%d %d",&n,&m); 
    for(int i=1;i<=n;i++) 
    { 
        scanf("%d %s",&Mode[i],str); 
        Map[i]=str; 
    } 
    int now=1; 
    while(m--) 
    { 
        scanf("%d %d",&dir,&val); 
        dir^=Mode[now]; 
        if(!dir)  
        { 
            val%=n; 
            now-=val; 
            if(now<=0) now+=n; 
        }else
        { 
            val%=n; 
            now+=val; 
            now%=n; 
            if(!now) now=n;  
        } 
    } 
    cout<<Map[now]<<endl; 
} 

天天愛跑步

時間限制: 2 Sec 內存限制: 512 MB
提交: 57 解決: 21
[提交][狀態][討論版]

題目描述

小C同學認為跑步非常有趣,於是決定制作一款叫做《天天愛跑步》的遊戲。

《天天愛跑步》是一個養成類遊戲,需要玩家每天按時上線,完成打卡任務。

這個遊戲的地圖可以看作一棵包含n個結點和n1條邊的樹,每條邊連接兩個結點,且任意兩個結點存在一條路徑互相可達。樹上結點編號為從1到n的連續正整數。

現在有m個玩家,第i個玩家的起點為Si,終點為Ti 。每天打卡任務開始時,所有玩家在第0同時從自己的起點出發,以每秒跑一條邊的速度,不間斷地沿著最短路徑向著自己的終點跑去,跑到終點後該玩家就算完成了打卡任務。(由於地圖是一棵樹,所以每個人的路徑是唯一的)

小C想知道遊戲的活躍度,所以在每個結點上都放置了一個觀察員。在結點j的 觀察員會選擇在第Wj 秒觀察玩家,一個玩家能被這個觀察員觀察到當且僅當該玩家在第Wj秒也正好到達了結點j。小C想知道每個觀察員會觀察到多少人?

註意:我們認為一個玩家到達自己的終點後該玩家就會結束遊戲,他不能等待一段時間後再被觀察員觀察到。即對於把結點j作為終點的玩家:若他在第Wj 到達 終點,則在結點j的觀察員不能觀察到該玩家;若他正好在第Wj 秒到達終點,則在結點j的觀察員可以觀察到這個玩家。

輸入

第一行有兩個整數nm。其中n代表樹的結點數量,同時也是觀察員的數量,m代表玩家的數量。

接下來n−1行每行兩個整數uv,表示結點u到結點v有一條邊。

接下來一行n 個整數,其中第j個整數為Wj ,表示結點j出現觀察員的時間。

接下來m行,每行兩個整數SiTi ,表示一個玩家的起點和終點。

對於所有的數據,保證1 ≤ Si , Ti ≤ n , 0 ≤ Wj ≤ n

輸出

輸出1行n個整數,第j個整數表示結點j的觀察員可以觀察到多少人。

樣例輸入

6 3
2 3
1 2
1 4
4 5
4 6
0 2 5 1 2 3
1 5
1 3
2 6



5 3
1 2
2 3
2 4
1 5
0 1 0 3 0
3 1
1 4
5 5

樣例輸出

2 0 0 1 1 1


1 2 1 0 1
 

提示

【樣例 1 說明】

對於 1 號點, W1 = 0 ,故只有起點為 1 號點的玩家才會被觀察到,所以玩家 1 和玩家 2 被觀察到,共 2 人被觀察到。

對於 2 號點,沒有玩家在第 2 秒時在此結點,共 0 人被觀察到。

對於 3 號點,沒有玩家在第 5 秒時在此結點,共 0 人被觀察到。

對於 4 號點,玩家 1 被觀察到,共 1 人被觀察到。

對於 5 號點,玩家 1 被觀察到,共 1 人被觀察到。

對於 6 號點,玩家 3 被觀察到,共 1 人被觀察到。

難題,考試的時候想寫暴力但是先去啃第三題, 整理了一下思路,首先把從s->t的路徑拆成從s->lca以及lca->t的路程。 然後考慮到從s到lca的路上會遇到觀察員i可以推出deep[s]=deep[i]+w[i]; 所以對於每個人,所有deep[i]+w[i]=deep[s]的且位於s到lca的路徑上的觀察員都會遇上。如何判斷一個觀察員是否在i到s的路上??? 我們考慮用時間戳來做,這樣整個樹形的信息就能轉化為線性。 一個觀察員首先觀察到的是時間戳位於[Grey[u],Black[u]]中的玩家,但是有情況玩家並不經過這個觀察員(dfn[lca]>dfn[u]),怎麽辦? 用樹上差分的思想,在dfn[s]處+1,dfn[lca]處-1,對於每個deep[s]建一棵樹,統計一下即可。(主席樹優化) 另一半差不多 這裏的主席樹建樹時沒有依靠前一棵樹,可以直接重新建,查詢是對單棵線段樹進行區間查詢。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#define N 300040
using namespace std;
int n,m,dfn[N],In[N],cnt,ans[N],num,Out[N],Time;
int rep[N],head[N],next[N<<1],to[N<<1],watch[N],deep[N],root[N*3],Fa[N];
struct note{
    int s,t,lca;
}runner[N];
struct que{
    int id,v;
};
struct tree{
    int l,r,sum;
}T[N*75];
vector<que> ques[N];
int getrep(int u)
{
    if(u==rep[u]) return u;
    return rep[u]=getrep(rep[u]);
}
void change(int &now,int l,int r,int pos,int w)
{
    if(!pos) return;
    if(!now) now=++cnt;
    T[now].sum+=w;
    if(l==r) return;
    int mid=(l+r)>>1;
    if(pos<=mid) change(T[now].l,l,mid,pos,w);else
    change(T[now].r,mid+1,r,pos,w);
}
int query(int now,int l,int r,int x,int y)
{
    if(!now) return 0;
    if(l==x&&r==y) return T[now].sum;
    int mid=(l+r)>>1;
    if(x>mid) return query(T[now].r,mid+1,r,x,y);else
    if(y<=mid) return query(T[now].l,l,mid,x,y);else
    return query(T[now].l,l,mid,x,mid)+query(T[now].r,mid+1,r,mid+1,y);
}
void clear_rep()
{
    for(int i=1;i<=n;i++)
    rep[i]=i;
}
void make_way(int u,int v)
{
    to[++num]=v;
    next[num]=head[u];
    head[u]=num;
}
void tarjan(int u,int fa)
{
    dfn[u]=In[u]=++Time;
    for(int edge=head[u];edge;edge=next[edge])
    if(!In[to[edge]])
    {
        deep[to[edge]]=deep[u]+1;
        tarjan(to[edge],u);
        int v=to[edge];
        Fa[v]=u;
        rep[getrep(to[edge])]=u;
    }
    for(int i=0;i<ques[u].size();i++)
    if(In[ques[u][i].v]) runner[ques[u][i].id].lca=getrep(ques[u][i].v);
    Out[u]=Time;
}
void clear()
{
    memset(root,0,sizeof(root));
    for(int i=1;i<=cnt;i++) T[i].l=T[i].r=T[i].sum=0;
    cnt=0;
}
int main()
{
    scanf("%d %d",&n,&m);
    int u,v;
    for(int i=1;i<n;i++)
    {
        scanf("%d %d",&u,&v);
        make_way(u,v);make_way(v,u);
    }
    for(int i=1;i<=n;i++)scanf("%d",&watch[i]);
    clear_rep();
    for(int i=1;i<=m;i++){
        scanf("%d %d",&u,&v);
        runner[i].s=u,runner[i].t=v;
        ques[u].push_back((que){i,v});
        ques[v].push_back((que){i,u});
    }
    tarjan(1,0);
    int now;
    for(int i=1;i<=m;i++)
    {
        now=deep[runner[i].s];
        change(root[now],1,n,dfn[runner[i].s],1);
        change(root[now],1,n,dfn[Fa[runner[i].lca]],-1);
    }
    for(int i=1;i<=n;i++) ans[i]+=query(root[deep[i]+watch[i]],1,n,In[i],Out[i]);
    clear();
    for(int i=1;i<=m;i++)
    {
        now=deep[runner[i].s]-deep[runner[i].lca]*2+n*2;
        change(root[now],1,n,dfn[runner[i].t],1); 
        change(root[now],1,n,dfn[runner[i].lca],-1); 
    }
    for(int i=1;i<=n;i++) ans[i]+=query(root[watch[i]-deep[i]+n*2],1,n,In[i],Out[i]); 
    for(int i=1;i<n;i++) printf("%d ",ans[i]); 
    printf("%d\n",ans[n]); 
 } 

換教室

時間限制: 1 Sec 內存限制: 512 MB
提交: 72 解決: 17
[提交][狀態][討論版]

題目描述

對於剛上大學的牛牛來說,他面臨的第一個問題是如何根據實際情況申請合適的課程。

在可以選擇的課程中,有 2n節課程安排在 n個時間段上。在第 i( 1≤in)個時間段上,兩節內容相同的課程同時在不同的地點進行,其中,牛牛預先被安排在教室ci上課,而另一節課程在教室 di進行。

在不提交任何申請的情況下,學生們需要按時間段的順序依次完成所有的n節安排好的課程。如果學生想更換第i節課程的教室,則需要提出申請。若申請通過,學生就可以在第i個時間段去教室 di上課,否則仍然在教室 di上課。

由於更換教室的需求太多,申請不一定能獲得通過。通過計算,牛牛發現申請更換第 i節課程的教室時,申請被通過的概率是一個己知的實數 ki,並且對於不同課程的申請,被通過的概率是互相獨立的。

學校規定,所有的申請只能在學期開始前一次性提交,並且每個人只能選擇至多m節課程進行申請。這意味著牛牛必須一次性決定是否申請更換每節課的教室,而不能根據某些課程的申請結果來決定其他課程是否申請;牛牛可以申請自己最希望更換教室的m門課程,也可以不用完m個申請的機會,甚至可以一門課程都不申請。

因為不同的課程可能會被安排在不同的教室進行,所以牛牛需要利用課間時間從一間教室趕到另一間教室。

牛牛所在的大學有v個教室,有e條道路。每條道路連接兩間教室,並且是可

雙向通行的。

由於道路的長度和擁堵程度不同,通過不同的道路耗費的體力可能會有所不同。當第i(1in1)節課結束後,牛牛就會從這節課的教室出發,選擇一條耗費體力最少的路徑前往下一節課的教室。現在牛牛想知道,申請哪幾門課程可以使他因在教室間移動耗費的體力值的總和的期望值最小,請你幫他求出這個最小值。

現在牛牛想知道,申請哪幾門課程可以使他因在教室間移動耗費的體力值的總和的期望值最小,請你幫他求出這個最小值。

輸入

第一行四個整數n,m,v,en表示這個學期內的時間段的數量;m表示牛牛最多可以申請更換多少節課程的教室;v表示牛牛學校裏教室的數量;e表示牛牛的學校裏道路的數量。 第二行n個正整數,第i(1i n)個正整數表示ci ,即第i個時間段牛牛被安排上課的教室;保證1ci v。 第三行n個正整數,第 i(1in)個正整數表示 di ,即第i個時間段另一間上同樣課程的教室;保證1di v

第四行n個實數,第i(1i n)個實數表示ki ,即牛牛申請在第i個時間段更換教室獲得通過的概率。保證0ki1。

接下來e行,每行三個正整數ajbjwj,表示有一條雙向道路連接教室aj,bj,通過這條道路需要耗費的體力值是wj;保證1≤aj,bjv,1≤wj≤100。

保證1≤n≤2000,0≤m≤ 2000,1≤v≤300,0≤e≤90000。

保證通過學校裏的道路,從任何一間教室出發,都能到達其他所有的教室。

保證輸入的實數最多包含3位小數。

輸出

輸出一行,包含一個實數,四舍五入精確到小數點後恰好 2,表示答案。你的輸出必須和標準輸出完全一樣才算正確。

測試數據保證四舍五入後的答案和準確答案的差的絕對值不大於4×10-3。(如果你不知道什麽是浮點誤差,這段話可以理解為:對於大多數的算法,你可以正常地使用浮點數類型而不用對它進行特殊的處理)

樣例輸入

3 2 3 3
2 1 2
1 2 1
0.8 0.2 0.5
1 2 5
1 3 3
2 3 1


樣例輸出

2.80

提示


【樣例 1 說明】
所有可行的申請方案和期望收益如下表: 期望DP,前i個教室申請j次且第i間教室是否申請的最小期望值。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 2100
#define M 320 
using namespace std;
int d[N][N],c[N][2];
double f[N][N][2];
int n,m,v,e;
double w[N];
void floyd()
{
    for(int i=1;i<=v;i++)
       d[i][i]=0;
      for(int i=1;i<=e;i++)
      {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        d[y][x]=d[x][y]=min(d[x][y],z);
      }
      
      for(int k=1;k<=v;k++)
           for(int i=1;i<=v;i++)
            for(int j=1;j<=v;j++)
                 d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
}
void dp()
{
    for(int i=0;i<=n;i++)
           for(int j=0;j<=n;j++)
            for(int k=0;k<2;k++)
                 f[i][j][k]=2000000000.00;
    f[1][0][0]=0;
    if(m) f[1][1][1]=0;
    for(int i=2;i<=n;i++)
  {
       f[i][0][0]=f[i-1][0][0]+d[c[i-1][0]][c[i][0]];
       f[i][0][1]=1e60;       
    for(int j=1;j<=m;j++)
       {    
         f[i][j][0]=min(f[i-1][j][0]+d[c[i-1][0]][c[i][0]],f[i-1][j][1]+w[i-1]*d[c[i-1][1]][c[i][0]]+(1.0-w[i-1])*d[c[i-1][0]][c[i][0]]);
         f[i][j][1]=f[i-1][j-1][1]+w[i]*w[i-1]*d[c[i-1][1]][c[i][1]]+(1.0-w[i])*w[i-1]*d[c[i-1][1]][c[i][0]]+(1.0-w[i])*(1.0-w[i-1])*d[c[i-1][0]][c[i][0]]+w[i]*(1.0-w[i-1])*d[c[i-1][0]][c[i][1]];
         f[i][j][1]=min(f[i][j][1],f[i-1][j-1][0]+w[i]*d[c[i-1][0]][c[i][1]]+(1.0-w[i])*d[c[i-1][0]][c[i][0]]);
       }
  }             
}
int main()
{
    scanf("%d%d%d%d",&n,&m,&v,&e);
    memset(d,63,sizeof(d));
      for(int i=1;i<=n;i++)
           scanf("%d",&c[i][0]);
      for(int i=1;i<=n;i++)
           scanf("%d",&c[i][1]);
      for(int i=1;i<=n;i++)
           scanf("%lf",&w[i]);
       floyd();
       dp();
       double ans=2000000000.00;
       for(int i=0;i<=m;i++)
       ans=min(ans,min(f[n][i][1],f[n][i][0]));
      printf("%.2f",ans);
}

9-7測試總結