【比賽報告】非酋yyf的sif之旅 NOIP練習賽卷八
阿新 • • 發佈:2018-12-13
#include<cstdio> int a,b,c,d,e,f,g,h,k,x,y; int pt,lp,exp; int main() { //freopen("in.txt","r",stdin); scanf("%d%d%d%d%d%d%d%d%d%d%d",&a,&b,&c,&d,&e,&f,&g,&h,&k,&x,&y); pt=0,lp=d+x,exp=f; long long cnt=0; while(pt<y) { while(lp<b)cnt++,lp+=c; lp-=b;pt+=a;exp+=g; if(exp>=e)//沒加等號,只有96 { exp-=e; e+=k;c+=h;lp+=c; } } printf("%lld\n",cnt); return 0; }
總結
很水一題,據說是貪心……個人感覺倒像個模擬
(我會告訴你我比賽時被卡了等號沒有AC嗎)
#include<cstdio> const int M=8e4+5,C=3e3+5,N=45,S=N*C+M; int a[S],b[S],n,m,c,d,sum,hd[N],tl[N],s,q[N][S][2],f[S][N],p[S][N],pos[N],ans,Pos; //f[i][j]前i張牌連抽j次 p[i][j]記錄f[i][j]由哪個i轉移過來 int main() { //freopen("in.txt","r",stdin); scanf("%d%d%d%d",&n,&m,&c,&d);s=n*c+m; for(int i=1;i<=s;i++) scanf("%d",&a[i]),sum+=a[i]; for(int i=2;i<=c;i++) b[1]+=a[i]; for(int i=2;i<=s-c+1;i++) b[i]=b[i-1]-a[i]+a[i+c-1];//b[i]維護a[i+1]加到a[i+c-1] for(int i=1;i<=n;i++) hd[i]=1; for(int i=1;i<=s-c+1;i++) { if(i<=c){f[i][1]=b[i];continue;} for(int j=(i+c-2)/(c+d)+1;j<=(i+c-1)/c&&j<=n;j++) { if(hd[j-1]<=tl[j-1]&&q[j-1][hd[j-1]][1]<i-c-d)//隊頭超出範圍的出隊 hd[j-1]++; if(j-1>=(i-2)/(c+d)+1&&j-1<=(i-1)/c) {//能入隊的入隊 while(hd[j-1]<=tl[j-1]&&q[j-1][tl[j-1]][0]>=f[i-c][j-1]) tl[j-1]--; q[j-1][++tl[j-1]][0]=f[i-c][j-1];//0記錄的最大值 q[j-1][tl[j-1]][1]=i-c;//1記錄的位置 } f[i][j]=q[j-1][hd[j-1]][0]+b[i]; p[i][j]=q[j-1][hd[j-1]][1]; if(i>=s-c+1-d&&j==n&&ans<sum-f[i][j]) ans=sum-f[i][j],Pos=i; } } printf("%d\n",ans); for(int j=n;j;j--) pos[j]=Pos,Pos=p[Pos][j]; for(int i=1;i<=n;i++) printf("%d ",pos[i]); puts(""); return 0; }
總結
當時好像是寫了個0分的DP還是啥的,心態直接炸了,T3也沒咋寫就放棄了。自己的心態還是得練練,畢竟以後寫不來的比賽題多了去了(笑) 自己動態規劃太菜,這種狀態轉移方程都毫無頭緒。狀態轉移方程出來單調佇列就顯而易見了。
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int N=1e3+10; int n,score,judge,minn,maxn; double P[65][10],per[2][N][6],f[2][N][6],ans,add[65]; //f[i][j][k]表示第i個節奏打了j個combo之後k個節奏改判的期望得分 //per[i][j][k]表示轉移到f[i][j][k]的概率 bool to[2][N][6]; //to[i][j][k]表示f[i][j][k]是否轉移過 struct node{ int c,p,t;//c次概率p%持續t bool operator <(const node&rhs)const{ return t>rhs.t;} }gai[N]; int main() { //freopen("in.txt","r",stdin); scanf("%d%d%d",&n,&score,&judge); int c,p,s; for(int i=1;i<=score;i++) { scanf("%d%d%d",&c,&p,&s);//c次概率p%加s分 for(int j=c;j<=60;j+=c) add[j]+=1.000000*(double)(p*s)/100.000000;//當連擊數為j時期望加分 } for(int i=1;i<=judge;i++) scanf("%d%d%d",&gai[i].c,&gai[i].p,&gai[i].t); sort(gai+1,gai+judge+1);P[0][0]=1.0; for(int i=1;i<=60;i++)//60是1~5的lcm { double a=1.000000; for(int j=1;j<=judge;j++) { if(i%gai[j].c)continue; P[i][gai[j].t]+=a*(double)gai[j].p/100.000000; //combo為i時使用長度為gai[j].c的改判的概率大小 a=(a*(double)(100-gai[j].p))/100.000000;//沒有用 } P[i][0]=a;//沒有效果的概率 } to[0][0][0]=1;per[0][0][0]=1.000000; for(int i=0,o=1,t=0;i<n;i++) { //t的狀態轉移到o的狀態 int po;maxn=0; scanf("%d",&po);//第i次擊打的原始結果 memset(f[o],0,sizeof(f[o])); memset(per[o],0,sizeof(per[o])); memset(to[o],0,sizeof(to[o])); for(int j=0;j<=minn;j++) for(int k=0;k<6;k++) { if(!to[t][j][k])continue;//沒有轉移過 int co=(j+(po+k>=2))*(po>1||(k&&po));//combo數 int sp=(co-1)%60+1;//得到combo數對應迴圈節中位置 for(int l=0;l<6;l++) { if(!P[sp][l])//combo為sp,長度為l continue; int m=(k-1)>l?(k-1):l;//最長持續時間 int poi=min(2,po+(k>0&&po));//改判後的結果 f[o][co][m]+=(f[t][j][k]+(add[sp]+(double)(co+1)*poi)*per[t][j][k])*1.000000*P[sp][l]; per[o][co][m]+=per[t][j][k]*P[sp][l]; to[o][co][m]=1; maxn=max(maxn,co); } } minn=maxn;swap(o,t); } for(int i=0;i<=n;i++) for(int j=0;j<6;j++) ans+=f[n&1][i][j]; printf("%.6f\n",ans); return 0; }
總結
當時沒有做第三題。這個期望DP還是比較厲害的,有很多需要注意的地方和優化。阿福又學會了新招。
賽後總結
這篇比賽最精華的是後面兩道DP題。T2是一個單調佇列優化DP,說難呢也不是真的很難,但是自己確實不會寫。T3期望DP的大佬操作很厲害,好好看好好學。 自己動態規劃寫的很不好,可以考慮再寫一兩場比賽就去補專題。