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

NOIP 2014 提高组 题解

时间:2016-08-04 19:20:02      阅读:217      评论:0      收藏:0      [点我收藏+]

标签:

NOIP 2014 提高组 题解

No 1. 生活大爆炸版石头剪刀布

http://www.luogu.org/problem/show?pid=1328

这是道大水题,我都在想怎么会有人错了,没算法,直接模拟,别读错题.

 1 int wn[5][5]={{2,0,1,1,0},
 2               {1,2,0,1,0},
 3               {0,1,2,0,1},
 4               {0,0,1,2,1},
 5               {1,1,0,0,2}};
 6 
 7 int n,na,nb;
 8 int a[222],b[222];
 9 int s1,s2;
10 
11 int main()
12 {
13     ios_base::sync_with_stdio(0);
14     
15     cin>>n>>na>>nb;
16     
17     for(int i=1;i<=na;i++)
18     {
19         cin>>a[i];
20     }
21     
22     for(int i=1;i<=nb;i++)
23     {
24         cin>>b[i];
25     }
26     
27     int f1=0,f2=0;
28     
29     for(int i=1;i<=n;i++)
30     {
31         f1++;
32         f2++;
33         if(f1>na) f1=1;
34         if(f2>nb) f2=1;
35         if(wn[a[f1]][b[f2]]==1) s1++;
36         else if(wn[a[f1]][b[f2]]==0) s2++;
37     }
38     
39     cout<<s1<< <<s2<<endl;
40     
41     return 0;
42 }

No 2. 联合权值

http://www.luogu.org/problem/show?pid=1351

同样是水题,用加法结合律.

首先,距离为2的两点,必有一个节点与他们都相连.

第一个要求最大值,对于每个点,预处理出相邻的边中权值最大的两条边,枚举每个点,计算这两个值的乘积,求个最大值即可.

第二个,要求距离为2的点对的权值之和,那么,我们先确定某点对中间的那个点,设为p,并预处理出p与其相邻的点距离之和d,则与其相邻的某点q,在中心点为p的距离为二的一条路径上的权值之和为d(q,p)*d(m1,p)+d(q,p)*d(m2,p)+...+d(q,p)*d(mi,p)=d(q,p)*(d-d(q,p)) 其中mi为与p相邻的除q以外的点,共i个.

最后求和即可.

 1 long long n;
 2 const long long MOD=10007;
 3 long long w[222222];
 4 long long sum[222222];
 5 long long mx;
 6 long long ans;
 7 vector<long long> e[222222];
 8 long long m1[222222],m2[222222];
 9 
10 int main()
11 {   
12     scanf("%lld",&n);
13     
14     for(long long i=1;i<n;i++)
15     {
16         long long a,b;
17         scanf("%lld %lld",&a,&b);
18         e[a].pb(b);
19         e[b].pb(a);
20     }
21     
22     for(long long i=1;i<=n;i++)
23     {
24         scanf("%lld",&w[i]);
25     }
26     
27     for(long long i=1;i<=n;i++)
28     {
29         for(long long j=0;j<(long long)e[i].size();j++)
30         {
31             sum[i]+=w[e[i][j]]%MOD;
32             
33             if(w[e[i][j]]>m1[i])
34             {
35                 m2[i]=m1[i];
36                 m1[i]=w[e[i][j]];
37             }
38             else if(w[e[i][j]]>m2[i])
39             {
40                 m2[i]=w[e[i][j]];
41             }
42         }
43     }
44     
45     for(long long i=1;i<=n;i++)
46     {
47         mx=max(mx,m1[i]*m2[i]);
48     }
49     
50     printf("%lld ",mx);
51     
52     for(long long i=1;i<=n;i++)
53     {
54         for(long long j=0;j<(long long)e[i].size();j++)
55         {
56             ans=ans+(w[e[i][j]])*(sum[i]-w[e[i][j]]);
57             ans=ans%MOD;
58         }
59     }
60     
61     printf("%lld\n",ans);
62 
63     return 0;
64 }

No 3. 飞扬的小鸟

http://www.luogu.org/problem/show?pid=1941

dp

dp

dp

 

其实这题真心不难

不明白为何有许多人不会做........

我们用dp(i,j)表示鸟儿飞到第i根柱子的j高度处所用的最少跳跃步数.

Obviously,不跳,摔落比较好,所以先处理它.

明显的,dp[i+1][j-y[i]]=min(dp[i+1][j-y[i]],dp[i][j]).

当鸟儿跳的时候,要是到顶了不能继续跳,所以要分个类:

1.到顶了

dp[i][m]=min(dp[i][m],dp[i][j]+1)
dp[i+1][m]=min(dp[i+1][m],dp[i][j]+1)

2.没到顶

dp[i][j+x[i]]=min(dp[i][j+x[i]],dp[i][j]+1);
dp[i+1][j+x[i]]=min(dp[i+1][j+x[i]],dp[i][j]+1);

 

于是就可以写程序了...

  1 int dp[11111][1111];
  2 int l[11111],r[11111];
  3 int has[11111];
  4 int x[11111],y[11111];
  5 int ans;
  6 int n,m,k;
  7 
  8 int main()
  9 {
 10     ios_base::sync_with_stdio(0);
 11     
 12     cin>>n>>m>>k;
 13     
 14     for(int i=0;i<11111;i++)
 15     {
 16         l[i]=1;
 17         r[i]=m;
 18     }
 19     
 20     for(int i=0;i<n;i++)
 21     {
 22         cin>>x[i]>>y[i];
 23     }
 24     
 25     for(int i=0;i<k;i++)
 26     {
 27         int t1,t2,t3;
 28         cin>>t1>>t2>>t3;
 29         
 30         l[t1]=t2+1;
 31         r[t1]=t3-1;
 32         has[t1]=1;
 33     }
 34     
 35     for(int i=1;i<=n;i++)
 36     {
 37         has[i]+=has[i-1];
 38     }
 39     
 40     for(int i=1;i<=n;i++)
 41     {
 42         for(int j=0;j<=m;j++)
 43         {
 44             dp[i][j]=inf;
 45         }
 46     }
 47     
 48     for(int i=0;i<=n;i++)
 49     {
 50         for(int j=r[i]+1;j<=m;j++)
 51         {
 52             dp[i][j]=inf;
 53         }
 54         
 55         for(int j=l[i];j<=r[i];j++)
 56         {
 57             if(dp[i][j]<inf)
 58             {
 59                 ans=i;
 60                 
 61                 if(j>y[i])
 62                 {
 63                     dp[i+1][j-y[i]]=min(dp[i+1][j-y[i]],dp[i][j]);
 64                 }
 65             }
 66         }
 67         
 68         for(int j=l[i];j<=m;j++)
 69         {
 70             if(dp[i][j]<inf)
 71             {
 72                 if(m<j+x[i])
 73                 {
 74                     dp[i][m]=min(dp[i][m],dp[i][j]+1);
 75                     dp[i+1][m]=min(dp[i+1][m],dp[i][j]+1);
 76                 }
 77                 else
 78                 {
 79                     dp[i][j+x[i]]=min(dp[i][j+x[i]],dp[i][j]+1);
 80                     dp[i+1][j+x[i]]=min(dp[i+1][j+x[i]],dp[i][j]+1);
 81                 }
 82             }
 83         }
 84     }
 85     
 86     if(ans==n)
 87     {
 88         ans=inf;
 89         
 90         for(int i=l[n];i<=r[n];i++)
 91         {
 92             ans=min(ans,dp[n][i]);
 93         }
 94         
 95         cout<<1<<endl<<ans<<endl;
 96     }
 97     else
 98     {
 99         cout<<0<<endl<<has[ans]<<endl;
100     }
101     
102     return 0;
103 }

 

先写day1 以后有时间再写day 2.........


 

NOIP 2014 提高组 题解

标签:

原文地址:http://www.cnblogs.com/nflslzt/p/5737875.html

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