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

【noip 2016】提高组

时间:2017-07-01 18:21:55      阅读:295      评论:0      收藏:0      [点我收藏+]

标签:int   line   ros   ide   dir   else   scanf   opened   题目   

D1T1.玩具谜题

题目链接

直接模拟就好了……water。(然而比赛的时候数组开少了一个0)

技术分享
 1 #include<cstdio>
 2 int n,m,a,s,ans;
 3 struct node{char name[12];int dir;}x[100050];
 4 int main()
 5 {
 6     scanf("%d%d",&n,&m);
 7     for(int i=0;i<n;i++)scanf("%d%s",&x[i].dir,x[i].name);
 8     while(m--)
 9     {
10         scanf("%d%d",&a,&s);
11         if(a==x[ans].dir)ans-=s;
12         else ans+=s;
13         if(ans<0)ans+=n;
14         ans%=n;
15     }
16     printf("%s",x[ans].name);
17     return 0;
18 }
View Code

D1T2.天天爱跑步

题目链接

因为太菜了,至今不会这道题……先扔题目链接,以后再回来把坑填了(flag

D1T3.换教室

题目链接

最短路+期望dp。

数组dp[i][j][k]代表当前进行到第i个时间段,已经更换了j门课程;若k=0则代表当前时间段不更换教室,k=1则代表当前时间段更换教室。

记得最后再循环一下dp[n][j][k],输出最优解。

技术分享
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int N=2050;
 6 const double inf=1e15;
 7 int n,m,v,e,a,b,c[N],d[N];
 8 double w,k[N],dp[N][N][2],dis[N][N];
 9 int read()
10 {
11     int x=0,f=1;char c=getchar();
12     while(c<0||c>9){if(c==-)f=-1;c=getchar();}
13     while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
14     return x*f;
15 }
16 void floyd()
17 {
18     for(int k=1;k<=v;k++)
19         for(int i=1;i<=v;i++)
20             for(int j=1;j<=v;j++)
21                 dis[i][j]=dis[j][i]=min(dis[i][j],dis[i][k]+dis[k][j]);
22 }
23 int main()
24 {
25     n=read();m=read();v=read();e=read();
26     for(int i=1;i<=n;i++)c[i]=read();
27     for(int i=1;i<=n;i++)d[i]=read();
28     for(int i=1;i<=n;i++)scanf("%lf",&k[i]);
29     for(int i=1;i<=v;i++)
30         for(int j=1;j<=v;j++)
31             if(i!=j)dis[i][j]=inf;
32     for(int i=0;i<=n;i++)
33         for(int j=0;j<=m;j++)
34             dp[i][j][0]=dp[i][j][1]=inf;
35     for(int i=1;i<=e;i++)
36         a=read(),b=read(),scanf("%lf",&w),dis[a][b]=dis[b][a]=min(dis[a][b],w);
37     floyd();
38     dp[1][0][0]=0;dp[1][1][1]=0;
39     for(int i=2;i<=n;i++)
40         for(int j=0;j<=m;j++)
41         {
42             if(j==0)dp[i][j][0]=min(dp[i][j][0],dp[i-1][j][0]+dis[c[i-1]][c[i]]);
43             else
44             {
45                 dp[i][j][0]=min(dp[i][j][0],dp[i-1][j][0]+dis[c[i-1]][c[i]]);
46                 dp[i][j][0]=min(dp[i][j][0],dp[i-1][j][1]+dis[d[i-1]][c[i]]*k[i-1]+dis[c[i-1]][c[i]]*(1-k[i-1]));
47                 dp[i][j][1]=min(dp[i][j][1],dp[i-1][j-1][0]+dis[c[i-1]][d[i]]*k[i]+dis[c[i-1]][c[i]]*(1-k[i]));
48                 dp[i][j][1]=min(dp[i][j][1],dp[i-1][j-1][1]+dis[c[i-1]][c[i]]*(1-k[i-1])*(1-k[i])+dis[c[i-1]][d[i]]*(1-k[i-1])*k[i]
49                 +dis[d[i-1]][c[i]]*k[i-1]*(1-k[i])+dis[d[i-1]][d[i]]*k[i-1]*k[i]);
50             }
51         }
52     double ans=inf;
53     for(int i=0;i<=m;i++)
54     {
55         ans=min(ans,dp[n][i][0]);
56         ans=min(ans,dp[n][i][1]);
57     }
58     printf("%.2lf",ans);
59     return 0;
60 }
View Code

D2T1.组合数问题

题目链接

杨辉三角打个表,然后前缀和优化优化(get到新姿势

技术分享
 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 using namespace std;
 5 const int N=2005;
 6 long long n,m,t,k,f[N][N],sum[N][N];
 7 long long read()
 8 {
 9     long long x=0,f=1;char c=getchar();
10     while(c<0||c>9){if(c==-)f=-1;c=getchar();}
11     while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
12     return x*f;
13 }
14 int main()
15 {
16     t=read();k=read();
17     for(int i=0;i<N;i++)f[i][0]=1;
18     for(int i=1;i<N;i++)
19         for(int j=1;j<=i;j++)
20         {
21             f[i][j]=(f[i-1][j]+f[i-1][j-1])%k;
22             if(!f[i][j])sum[i][j]=1;
23             sum[i][j]+=sum[i][j-1];
24         }
25     while(t--)
26     {
27         long long ans=0;
28         n=read();m=read();
29         for(long long i=1;i<=n;i++)
30             ans+=sum[i][min(m,i)];
31         printf("%lld\n",ans);
32     }
33     return 0;
34 }
View Code

D2T2.蚯蚓

题目链接

维护三个队列:q1是原数列(先从大到小sort一波),q2是砍完之后的前段,q3是砍完之后的后段(依据题意易得,q2、q3单调递减)。每次从三个队列的队头元素取出最大的一个进行切断操作并在队列中删去它,再将砍完后生成的两个新数分别存入q2、q3。

至于每次操作完增加的长度……直接用时间算就好了?

技术分享
 1 #include<cstdio>
 2 #include<cmath>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int N=100050;
 7 const int M=7000050;
 8 double p;
 9 int h1=1,h2=1,t2,h3=1,t3;
10 long long n,m,q,u,v,t;
11 long long q1[N],q2[M],q3[M];
12 long long read()
13 {
14     long long x=0,f=1;char c=getchar();
15     while(c<0||c>9){if(c==-)f=-1;c=getchar();}
16     while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
17     return x*f;
18 }
19 bool cmp(long long a,long long b){return a>b;}
20 long long get(int tim)
21 {
22     long long x=-0x3f3f3f3f3f3f3f3f;
23     if(h1<=n&&q1[h1]>x)x=q1[h1];
24     if(h2<=t2&&q2[h2]>x)x=q2[h2];
25     if(h3<=t3&&q3[h3]>x)x=q3[h3];
26     if(h1<=n&&x==q1[h1])h1++;
27     else if(h2<=t2&&x==q2[h2])h2++;
28     else h3++;
29     return x+(tim-1)*q;
30 }
31 int main()
32 {
33     n=read();m=read();q=read();u=read();v=read();t=read();p=1.0*u/v;
34     for(int i=1;i<=n;i++)q1[i]=read();
35     sort(q1+1,q1+n+1,cmp);
36     for(int i=1;i<=m;i++)
37     {
38         long long k=get(i);
39         if(i%t==0)printf("%lld ",k);
40         long long k1=floor(k*p),k2=k-k1;
41         q2[++t2]=k1-q*i;q3[++t3]=k2-q*i;//注意-q*i!
42     }
43     printf("\n");
44     for(int i=1;i<=n+m;i++)
45     {
46         long long k=get(m+1);
47         if(i%t==0)printf("%lld ",k);
48     }
49     return 0;
50 }
View Code

D3T3.愤怒的小鸟

题目链接

状压dp……注意精度问题。

f[i][j]代表当第i只小猪与第j只小猪配对时,小鸟的飞行轨迹可以消灭的小猪的状态。处理完就先枚举当前状态,然后枚举第一只尚未配对的小猪,再枚举与其配对的小猪,直接dp。

注意:有可能一只小鸟只消灭了一只小猪。

技术分享
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cmath>
 4 #include<algorithm>
 5 using namespace std;
 6 int T,n,m,id[20],f[20][20],dp[1<<20];
 7 double a,b,x[20],y[20];
 8 bool pan(double x,double y){return fabs(x-y)<1e-6;}
 9 void solve()
10 {
11     scanf("%d%d",&n,&m);
12     for(int i=1;i<=n;i++)scanf("%lf%lf",&x[i],&y[i]);
13     memset(f,0,sizeof(f));
14     for(int i=1;i<=n;i++)
15         for(int j=i+1;j<=n;j++)
16         {
17             if(pan(x[i],x[j]))continue;
18             a=(y[j]/x[j]-y[i]/x[i])/(x[j]-x[i]);
19             if(a>=0)continue;
20             b=y[i]/x[i]-a*x[i];
21             int t=0;
22             for(int k=1;k<=n;k++)
23                 if(pan(a*x[k]+b,y[k]/x[k]))t+=id[k];
24             f[i][j]=t;
25         }
26     memset(dp,0x3f,sizeof(dp));dp[0]=0;
27     for(int i=0;i<(1<<n);i++)
28         for(int j=1;j<=n;j++)
29         {
30             if(i&id[j])continue;
31             for(int k=j+1;k<=n;k++)
32                 dp[i|f[j][k]]=min(dp[i|f[j][k]],dp[i]+1);
33             dp[i|id[j]]=min(dp[i|id[j]],dp[i]+1);//注意处理一只小鸟只消灭一只小猪的情况!
34         }
35     printf("%d\n",dp[(1<<n)-1]);
36 }
37 int main()
38 {
39     for(int i=1;i<=19;i++)id[i]=1<<(i-1);
40     scanf("%d",&T);
41     while(T--)solve();
42     return 0;
43 }
View Code

 

【noip 2016】提高组

标签:int   line   ros   ide   dir   else   scanf   opened   题目   

原文地址:http://www.cnblogs.com/zsnuo/p/7102685.html

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