首页 > 代码库 > 2016.10.29 清北学堂NOIP冲刺班Day1 AM 考试总结

2016.10.29 清北学堂NOIP冲刺班Day1 AM 考试总结

成绩:满分300,我得了200,

1:90//前两个题目都是模拟,没用到什么其他算法,第一题有可能少考虑了一点细节

2:100

3:10//感觉是个DP,但是毫无思路,只打了个普通背包,10分而已。

题目+数据:http://pan.baidu.com/s/1bpj3SR1

下面是我的代码:

 

这个题目中我为了得到部分分,而特别判断了几组数据。

T1:

 1 /*
 2 以后一定要仔细读数据范围,一定要。
 3 数据范围中:20%的数据,只有秒数可能不同,言外之意就是可能相同。
 4 而我的程序因为没有考虑到,时间相同时直接输出0000,。O__O"…
 5 
 6 一个小技巧:计算时间时,可以把所有的时间都换算成秒,直接总秒数1-秒数2,不仅不会溢出,而且也方便计算。
 7 */
 8 #include<iostream>
 9 using namespace std;
10 #include<cstdio>
11 typedef long long ll;
12 struct Tim{
13     int n,y,r,x,f,m;
14 }tim1,tim2;
15 long long ans=0;
16 int mon[15]={0,31,28,31,30,31,30,31,31,30,31,30,31};
17 bool is_runnian(int x)
18 {
19     if(x%400==0) return true;
20     if(x%100!=0&&x%4==0) return true;
21     return false;
22 } 
23 
24 void input()
25 {
26     scanf("%d-%d-%d %d:%d:%d",&tim1.n,&tim1.y,&tim1.r,&tim1.x,&tim1.f,&tim1.m);
27     scanf("%d-%d-%d %d:%d:%d",&tim2.n,&tim2.y,&tim2.r,&tim2.x,&tim2.f,&tim2.m);
28 }
29 int main()
30 {
31 //    freopen("two.in","r",stdin);
32 //    freopen("two.out","w",stdout);
33     input();
34     if(tim1.n==tim2.n&&tim1.y==tim2.y&&tim1.r==tim2.r)
35     {
36         ans=(ll)(tim2.x*3600+tim2.f*60+tim2.m)-(tim1.x*3600+tim1.f*60+tim1.m);
37     }
38     else  if(tim1.n==tim2.n)
39           {
40               ll d1=0,d2=0;
41               for(int i=1;i<tim1.y;++i)
42                  d1+=mon[i];
43             if(is_runnian(tim1.n)&&tim1.y>2) d1++;
44             for(int i=1;i<tim2.y;++i)
45                d2+=mon[i];
46             if(is_runnian(tim2.n)&&tim2.y>2) d2++;
47             d1+=tim1.r;
48             d2+=tim2.r;
49            ans=(ll)(d2*24*3600+tim2.x*3600+tim2.f*60+tim2.m)-(ll)(d1*24*3600+tim1.x*3600+tim1.f*60+tim1.m);
50               
51           }
52           else{
53               ll d1=0,d2=0;
54               for(int i=2000;i<tim1.n;++i)
55                 if(is_runnian(i)) d1+=366;
56                 else d1+=365;
57               for(int i=2000;i<tim2.n;++i)
58                 if(is_runnian(i)) d2+=366;
59                 else d2+=365;
60               for(int i=1;i<tim1.y;++i)
61                  d1+=mon[i];
62             if(is_runnian(tim1.n)&&tim1.y>2) d1++;
63             for(int i=1;i<tim2.y;++i)
64                d2+=mon[i];
65             if(is_runnian(tim2.n)&&tim2.y>2) d2++;
66             d1+=tim1.r;
67             d2+=tim2.r;
68            ans=(ll)(d2*24*3600+tim2.x*3600+tim2.f*60+tim2.m)-(ll)(d1*24*3600+tim1.x*3600+tim1.f*60+tim1.m);
69           }
70     if(ans) cout<<ans<<"000";
71     else printf("0\n");
72     fclose(stdin);
73     fclose(stdout);
74     return 0;
75 }

 

T2:

 1 #include<iostream>
 2 using namespace std;
 3 #include<cstdio>
 4 #define N 100010
 5 #define M 50010
 6 #include<algorithm>
 7 #include<queue>
 8 typedef long long ll;
 9 struct node{
10     ll tim;
11     bool operator <(node P)
12     const{return tim>P.tim;}
13 };
14 priority_queue<node>Q;
15 ll ren[N];
16 int n,m;
17 ll read()
18 {
19     ll ret=0;
20     char s=getchar();
21     while(s<0||s>9)
22     {
23         s=getchar();
24     }
25     while(s>=0&&s<=9)
26     {
27         ret=ret*10+s-0;
28         s=getchar();
29     }
30     return ret;
31 }
32 void input()
33 {
34     scanf("%d%d",&n,&m);
35     for(int i=1;i<=n;++i)
36       ren[i]=read();
37     for(int i=1;i<=m;++i)
38     {
39         node X;
40         X.tim=ren[i];
41         Q.push(X);
42     }
43 }
44 int main()
45 {
46     freopen("death.in","r",stdin);
47     freopen("death.out","w",stdout);
48     input();
49     for(int i=m+1;i<=n;++i)
50     {
51         node Now=Q.top();
52         Q.pop();
53         Now.tim+=ren[i];
54         Q.push(Now);
55     }
56     printf("%I64d",Q.top());
57     fclose(stdin);
58     fclose(stdout);
59     return 0;
60 }

 T3:

解析:

看了看题解:感觉也是这个道理:也许它并不需要Dp,比如在1*31*2)中,我们为了价值最大,肯定先放价值大的(因为体积相同嘛),所以我们就把
价值大的先放进去就可以了。
这个题目注意两点即可:

1.有很多体积相同但是价值不同的物品,可以直接用贪心排序,就可以了。

2.不必关注具体的背包中的物品如何放置,只需要关注能放多少个就可以了。因为我们总有办法使放到几乎满了或者满了的情况。

所以思路:
可以直接用n*m/3,n*m/2,计算数目,但是我们要想一想这样有没有可能出现错误。
n*m/2情况,如果n*m的背包1*2这么放,那么最后只可能

 

余下一个空位置,那么结果是不错的,但是如果是n*m的情况,我们可以发现,如果满足
n%3==2 && m%3==2 && (n==2 || m==2),如果只放1*3,最后会余下一个2*2的正方形不能再放,但是如果直接用n*m/3的话,结果就会多1了。

 

 1 #include<iostream>
 2 using namespace std;
 3 #include<cstdio>
 4 #include<algorithm>
 5 #include<cstring>
 6 #define N 10010
 7 int t,n,m,n1,n2,wu1[N],wu2[N];
 8 int sumwu1[N],sumwu2[N];
 9 typedef long long ll;
10 bool cmp1(int a,int b)
11 {
12     return a>b;
13 }
14 int main()
15 {
16 //    freopen("eyesight.in","r",stdin);
17 //    freopen("eyesight.out","w",stdout);
18     scanf("%d",&t);
19     while(t--)
20     {
21         scanf("%d%d%d%d",&n,&m,&n1,&n2);
22         memset(sumwu1,0,sizeof(sumwu1));
23         memset(sumwu2,0,sizeof(sumwu2));
24         for(int i=1;i<=n1;++i)
25           scanf("%d",&wu1[i]);
26         for(int i=1;i<=n2;++i)
27           scanf("%d",&wu2[i]);
28         sort(wu1+1,wu1+n1+1,cmp1);
29         sort(wu2+1,wu2+n2+1,cmp1);
30         for(int i=1;i<=n1;++i)
31           sumwu1[i]=sumwu1[i-1]+wu1[i];
32         for(int i=1;i<=n2;++i)
33           sumwu2[i]=sumwu2[i-1]+wu2[i];
34         ll ans=0;
35         int dalta;
36         if(n%3==2&&m%3==2&&(n==2||m==2)) dalta=4;
37         else dalta=n*m%3;
38         int sum=min(n2,(n*m-dalta)/3);
39         for(int i=0;i<=sum;++i)
40           ans=max(ans,(ll)(sumwu2[i]+sumwu1[min(n1,(n*m-3*i)>>1)]));
41         cout<<ans<<endl;
42         
43     }
44     fclose(stdin);
45     fclose(stdout);
46     return 0;
47 }

 

2016.10.29 清北学堂NOIP冲刺班Day1 AM 考试总结