首页 > 代码库 > 2017/8/6 考试吐槽

2017/8/6 考试吐槽

2016 8 6 成绩:20

(既然翻车了就多扯几句,反正也不怕什么,都是自己人)

得知成绩的一刻瘫倒在了地上……满怀希望的一场考试竟是这样的一场大翻车……只能用惨烈形容了……我菜爆了……一天天依赖STL都有毒啊……我说啥啊……能说的全卡在嗓子眼出不来啊……我真……菜的抠脚!唉……全都考好了,自己弱也怪不得出题人……算了先到这里,先开始口胡

A、天鹅会面

首先贴出一个英吹四艇的OJ上的链接:http://codeup.hustoj.com/problem.php?id=25481&csrf=5dMbAI0PV08sOXYR8BRfAmofZXVUkBUK

题意:有一个目前是不连通的图,与连通的部分相接的不连通部分会转变为联通部分,问多久后源汇连通。

吐槽&题解(今天分不出来啊……坑点就是吐槽点……全中招了……):论垃圾题面的危害……看题面都知道是一个傻逼bfs,先是一遍bfs跑出各个联通块联通的时间,随后第二遍bfs判断起终点联通块联通需要的时间。但是……坑点1:考试时包括我的一大圈子人被误导为一天只走一个方向,实际上整个图都可以走,GG;坑点2:原题丧心病狂卡STL,删去STL::queue后加快300+ms,然而考试并不知道,GG;坑点3:迷之剪枝,不剪最后一个点+1s,GG……三大坑点,愉♂悦地爆零了……(感谢@hzoi-mafia wcx神犇的援助)

技术分享
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 struct pii
 7 {
 8     int first,second;
 9 };
10 const int maxn=1505,inf=2147483647;
11 pii q[25000005];
12 int n,m,map[maxn][maxn],ice[maxn][maxn],x[2],y[2],cnt,dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
13 bool vis[maxn][maxn];
14 char s[maxn];
15 void bfs0()
16 {
17     int head=0,tail=0;
18     for(int i=1;i<=n;i++)
19         for(int j=1;j<=m;j++)
20             if(!ice[i][j])
21                 q[tail++]=(pii){i,j};
22     while(head!=tail)
23     {
24         pii s=q[head++];
25         int X=s.first,Y=s.second;
26         for(int k=0;k<4;k++)
27         {
28             int i=X+dx[k],j=Y+dy[k];
29             if(i<1||i>n||j<1||j>m)continue;
30             if(ice[i][j]==inf||ice[i][j]>ice[X][Y]+1)
31             {
32                 ice[i][j]=ice[X][Y]+1;
33                 q[tail++]=(pii){i,j};
34             }
35         }
36     }
37 }
38 void bfs()
39 {
40     int head=0,tail=0;
41     q[tail++]=(pii){x[0],y[0]};vis[x[0]][y[0]]=1;
42     while(head!=tail)
43     {
44         pii s=q[head++];
45         int X=s.first,Y=s.second;vis[X][Y]=0;
46         for(int k=0;k<4;k++)
47         {
48             int i=X+dx[k],j=Y+dy[k];
49             if(i<1||i>n||j<1||j>m)continue;
50             if(map[i][j]>map[X][Y]&&map[i][j]!=ice[i][j])
51             {
52                 map[i][j]=max(map[X][Y],ice[i][j]);
53                 if(!vis[i][j])q[tail++]=(pii){i,j},vis[i][j]=1;
54             }
55         }
56     }
57 }
58 int haha()
59 {
60     scanf("%d%d",&n,&m);
61     for(int i=1;i<=n;i++)
62     {
63         scanf("%s",s+1);
64         for(int j=1;j<=m;j++)
65             switch(s[j])
66             {
67                 case X:map[i][j]=ice[i][j]=inf;break;
68                 case .:map[i][j]=inf;ice[i][j]=0;break;
69                 case L:map[i][j]=cnt==1?inf:0;ice[i][j]=0;x[cnt]=i;y[cnt]=j;cnt++;break;
70             }
71     }
72     bfs0();bfs();
73     printf("%d\n",map[x[1]][y[1]]);
74 }
75 int sb=haha();
76 int main(){;}
A

B、选美

链接:http://codeup.hustoj.com/problem.php?id=25482&csrf=z9b457TsUSu8fGL3ySDZg3ibmj8BMPpW

题意:每个人有两个属性$H$和$W$,选择人时要满足公式:$A(H? h)+B(W? w)<=C$,,三个大写字母代表的常数参数已给出,其中大写字母代表本人,小写字母代表全队中两个值的最小值,求最多能收走几个妹子。

吐槽&题解:没啥说的了……暴力分不要我也没有办法……下面开始介绍 whm神犇的思路:

$A(H? h)+B(W? w)<=C$运用高级数学知识:不等式移项可以得到下式:$A(H? h)+B*W?C<=B*w$,那么我们就利用这个式子,对于每一个人假设他的h最小,然后枚举比他高的每一个人的$w$,求出$w$范围的并,最后差分乱搞就可以啦……看上去时限是$O(n^2)$,然而人傻自带超大常数,所以被wq dalao 多一个$log$踩了过去,orz……另外orz gxy dalao,$O(n^3)$暴力过啦……太神啦……

PS:垃圾出题人……数据范围打错……卡的寻死觅活……

技术分享
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 using namespace std;
 6 const int maxn=2005;
 7 int n,A,B,C,w[maxn],h[maxn],f[maxn],ans,seq[100005],maxx;
 8 int haha()
 9 {
10     //freopen("beauty.in","r",stdin);
11     //freopen("beauty.out","w",stdout);
12     scanf("%d%d%d%d",&n,&A,&B,&C);
13     for(int i=1;i<=n;i++)scanf("%d%d",&h[i],&w[i]);
14     for(int i=1;i<=n;i++)
15     {
16         //cout<<i<<endl;
17         memset(seq,0,sizeof(seq));
18         int maxl=0;
19         for(int j=1;j<=n;j++)
20         {
21             maxl=0;
22             if(h[j]>=h[i]&&A*(h[j]-h[i])<=C)
23             {
24                 maxl=max(maxl,(A*h[j]-A*h[i]+B*w[j]-C)/B);
25                 maxl=min(maxl,w[j]);
26                 maxl=max(maxl,0);
27                 seq[maxl]++;seq[w[j]+1]--;
28             }
29         }
30         for(int j=0;j<=100000;j++)seq[j]+=seq[j-1];
31         for(int j=1;j<=n;j++)
32             if(h[j]>=h[i]&&A*(h[j]-h[i])<=C)
33                 ans=max(ans,seq[w[j]]);
34     }
35     printf("%d\n",ans);
36 }
37 int sb=haha();
38 int main(){;}
B

C、拯救莫莉斯

这题据说是GDOI2014 的题,但是好像GDOI2014集体被续了一样……一道题也找不到……有找到的读者大爷可以告诉我我可以加上然而蒟蒻的博客又会有谁看呢

题意:找到最省钱,在此基础上最省次数的建设油库方法,使全矩阵任意一点与油库曼哈顿距离不大于1。

吐槽&题解:我的眼睛还没瞎成功发现数据范围是$n*m<=50,m<=n$,得出$m<=7$,成功想到状压……然而有时候记性太好也不是什么好事……条件反射式的想起了前几天的那道毒瘤大爆搜(出门左转:http://www.cnblogs.com/Loser-of-Life/p/7275536.html的B)……枚举第一行做法过于深入人心……于是成功被错误思路带进沟,GG……

正确思路是dp……设数组$f[i][j][k]$为当前在第$i$行,前一行状态为$j$,本行状态为$k$,那么转移方程就是$f[i+1][k][l]=min{f[i][j][k]+cost[i+1][l]|0<=l<2^m}$,其中$l$为下一层的情况,$cost[i][j]$为在第$i$行买出$j$状态的花费。为了保证这一行要满足条件,转移的前提还有一个:$(k    or      l     or      j     or     (k*2)    or   (k/2)) and (2^m-1)=2^m-1$之后瞎转就是了,最后结果就是$min{f[n+1][j][0]|0<=j<=2^m-1}$。

技术分享
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int maxn=55,maxa=128;
 7 int n,m,map[maxn][maxn];
 8 int f[maxn][maxa][maxa],cost[maxn][maxa],num[maxn][maxa][maxa],cnt[maxn][maxa];
 9 int convert(int line,int val)
10 {
11     int res=0,rec=val;
12     for(int pos=0;val;val>>=1,pos++)
13         if(val&1){res+=map[line][m-pos];cnt[line][rec]++;}
14     //cout<<line<<" "<<rec<<" "<<res<<endl;
15     return res;
16 }
17 int haha()
18 {
19     //freopen("proj.in","r",stdin);
20     //freopen("proj.out","w",stdout);
21     scanf("%d%d",&n,&m);
22     for(int i=1;i<=n;i++)
23         for(int j=1;j<=m;j++)scanf("%d",&map[i][j]);
24     int att=(1<<m);
25     for(int i=1;i<=n+1;i++)
26         for(int j=0;j<att;j++)cost[i][j]=convert(i,j);
27     memset(num,0x7f,sizeof(num));
28     memset(f,0x7f,sizeof(f));num[0][0][0]=f[0][0][0]=0;
29     for(int i=0;i<=n;i++)
30         for(int j=0;j<att;j++)
31             for(int k=0;k<att;k++)
32                 for(int l=0;l<att;l++)
33                     if(((k|j|l|(k<<1)|(k>>1))&(att-1))==att-1||!i)
34                     {
35                         //cout<<i<<" "<<k<<" "<<j<<" "<<l<<endl;
36                         //system("pause");
37                         if(f[i][j][k]+cost[i+1][l]<f[i+1][k][l]||(f[i][j][k]+cost[i+1][l]==f[i+1][k][l]&&num[i][j][k]+cnt[i+1][l]<num[i+1][k][l]))
38                         {
39                             f[i+1][k][l]=f[i][j][k]+cost[i+1][l];
40                             num[i+1][k][l]=num[i][j][k]+cnt[i+1][l];
41                         }
42                     }
43     int ans=2147483647,Num=2147483647;                    
44     for(int i=0;i<att;i++)
45         if(ans>f[n+1][i][0]||(ans==f[n+1][i][0]&&num[n+1][i][0]<Num))
46         {
47             ans=f[n+1][i][0];
48             Num=num[n+1][i][0];
49             //cout<<i<<endl;
50         }
51     /*for(int j=0;j<att;j++)
52     {
53         cout<<f[n+1][j][0]<<endl;
54     }*/
55     //cout<<f[1][0][0]<<endl;
56     printf("%d %d",Num,ans);
57 }
58 int sb=haha();
59 int main(){;}
C

 

2017/8/6 考试吐槽