NOIp 2013 Day2 解题报告
1. 积木大赛
每次只要选取连续最大的一段区间即可。
继续归纳可得,答案为∑i=1nmax{0,hi-hi-1}
复杂度O(N)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 8 //variable// 9 int n,h[101000],ans; 10 11 //solve// 12 int main(){ 13 scanf("%d",&n); 14 for (int i=1;i<=n;++i){ 15 scanf("%d",h+i); 16 ans+=max(0,h[i]-h[i-1]); 17 } 18 printf("%d\n",ans); 19 return 0; 20 }
2. 花匠
题目要求我们选出一个“锯齿型”的序列。
一个很容易证明的贪心策略是:每次选取序列中的单调性改变的点,即为“拐点”。
复杂度O(N)
这里注意到,“拐点”可能是一个连续的值相等的区间,需要特殊处理。由于题目中不允许在求出的序列中出现连续两个数相等的情况,所以我们可以在读入中直接筛去于前面的数相等的数。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 8 //variable// 9 int n,h[100100],ans=0,tot=1; 10 11 //solve// 12 int main(){ 13 scanf("%d",&n); 14 for (int i=1;i<=n;++i){ 15 scanf("%d",h+tot); 16 if (h[tot]!=h[tot-1]){ 17 ++tot; 18 } 19 } 20 --tot; 21 for (int i=2;i<tot;++i){ 22 if (((long long)h[i]-h[i-1])*((long long)h[i]-h[i+1])>0){ 23 ++ans; 24 } 25 } 26 ans+=2; 27 printf("%d\n",ans); 28 return 0; 29 }
3. 华容道
对于60%的数据,我们直接让指定块和空位分别在i行j列、k行l列的状态作为一个点,位置空位点相邻的点之间或指定块和空位相邻且位置相反的点之间连权值为1的边,BFS,复杂度O(QN2M2)
我们发现,上述建图方法中有很多点是没有价值的。
题目要求为让指定块移至目标位置。然而,只有空位与指定块相邻时,指定块才能移动。所以,只有空位和指定块相邻的点是有价值的。
设lable[i][j][k]代表表示空位在位于i行j列的指定块的k号方向上(方向为上左下右,从0开始标号)的状态的点的标号,space_step[i][j][k][l]代表空位在位于i行j列的指定块的k号方向上移动到i行j列指定块的l号方向上所需最小步数,dx[i]和dy[i]分别代表标号为i的方向横纵坐标的差值。在lable[i][j][k]和lable[i+dx[l]][j+dy[l]][(l+2)%4]之间连一条权值为space_step[i][j][k][l]+1的边。对于每个询问,在这个图上spfa。
求space_step:枚举i和j,BFS记录深度。注意在BFS时要将map[i][j]置为不可达,否则求出的值就是改变了目标块位置的值。
spfa时,要将每个lable[sx][sy][i]的dis置为从ex行ey列BFS后对应的深度值,同时将这四个点加入队,再spfa,答案为dis[lable[tx][ty][0..3]]中的最小值。如果不按照上述方式将四个点同时入队再spfa而是分别spfa会错。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 8 //constant// 9 const int d[2][8]={{-1,-1,0,1,1,1,0,-1},{0,1,1,1,0,-1,-1,-1}};//shunshizhen up 10 11 //variable// 12 int q[1000000],dis[100000],dep[100000],vis[100000]; 13 int last[10000],totp=0,prel[100000],dest[100000],cost[100000],tot=0; 14 int n,m,map[35][35],lable[35][35][4],space_step[35][35][35][35],Q,ex,ey,sx,sy,tx,ty,L[4]; 15 16 //function prototype// 17 void addline(int,int,int); 18 void calc_lable(void); 19 void calc_step(void); 20 void calc_space_step(void); 21 void bfs(int,int,int,int); 22 int spfa(void); 23 24 //solve// 25 int main(){ 26 scanf("%d%d%d",&n,&m,&Q); 27 for (int i=1;i<=n;++i){ 28 for (int j=1;j<=m;++j){ 29 scanf("%d",map[i]+j); 30 } 31 } 32 calc_lable(); 33 calc_step(); 34 while (Q--){ 35 int ans=2140000000; 36 scanf("%d%d%d%d%d%d",&ex,&ey,&sx,&sy,&tx,&ty); 37 if (sx==tx&&sy==ty){ 38 puts("0"); 39 continue; 40 } 41 bfs(ex,ey,sx,sy); 42 ans=min(ans,spfa()); 43 printf("%d\n",ans<1000000000?ans:-1); 44 } 45 return 0; 46 } 47 48 int spfa(){ 49 memset(q,0,sizeof q); 50 memset(dis,0x7f,sizeof dis); 51 memset(vis,0,sizeof vis); 52 int he=500001,ta=500000; 53 for (int i=0;i<4;++i){ 54 if (dep[(sx+d[0][i<<1]-1)*m+sy+d[1][i<<1]]<1000000000){ 55 q[++ta]=lable[sx][sy][i]; 56 vis[lable[sx][sy][i]]=1; 57 dis[lable[sx][sy][i]]=dep[(sx+d[0][i<<1]-1)*m+sy+d[1][i<<1]]; 58 } 59 } 60 while (he<=ta){ 61 int u=q[he++]; 62 vis[u]=0; 63 for (int k=last[u];k;k=prel[k]){ 64 if (dis[dest[k]]>dis[u]+cost[k]){ 65 dis[dest[k]]=dis[u]+cost[k]; 66 if (!vis[dest[k]]){ 67 vis[dest[k]]=1; 68 if (he<=ta&&dis[dest[k]]<dis[q[he]]){ 69 q[--he]=dest[k]; 70 }else{ 71 q[++ta]=dest[k]; 72 } 73 } 74 } 75 } 76 } 77 int ret=2147000000; 78 for (int i=0;i<4;++i){ 79 if (lable[tx][ty][i]){ 80 ret=min(ret,dis[lable[tx][ty][i]]); 81 } 82 } 83 return ret; 84 } 85 86 void addline(int u,int v,int w){ 87 dest[++tot]=v; 88 prel[tot]=last[u]; 89 last[u]=tot; 90 cost[tot]=w; 91 } 92 93 void calc_lable(){ 94 for (int i=1;i<=n;++i) 95 for (int j=1;j<=m;++j) if (map[i][j]) 96 for (int spa=0;spa<4;++spa) if (map[i+d[0][spa<<1]][j+d[1][spa<<1]]) 97 lable[i][j][spa]=++totp; 98 } 99 100 void calc_step(){ 101 for (int i=1;i<=n;++i){ 102 for (int j=1;j<=m;++j) if (map[i][j]){ 103 for (int dire=0;dire<4;++dire) if (lable[i][j][dire]){ 104 bfs(i+d[0][dire<<1],j+d[1][dire<<1],i,j); 105 for (int spa=0;spa<4;++spa) if (lable[i][j][spa]){ 106 int w=dep[(i+d[0][spa<<1]-1)*m+j+d[1][spa<<1]]; 107 if (w<1000000000){ 108 addline(lable[i][j][spa],lable[i+d[0][dire<<1]][j+d[1][dire<<1]][(dire+2)%4],w+1); 109 } 110 } 111 } 112 } 113 } 114 } 115 116 void bfs(int x,int y,int sx,int sy){ 117 memset(q,0,sizeof q); 118 memset(dep,0x7f,sizeof dep); 119 int he=1,ta=1; 120 q[1]=(x-1)*m+y;dep[(x-1)*m+y]=0; 121 map[sx][sy]=0; 122 while (he<=ta){ 123 int u=q[he++]; 124 int locx=(u-1)/m+1,locy=(u-1)%m+1; 125 for (int k=0;k<8;k+=2){ 126 if (map[locx+d[0][k]][locy+d[1][k]]){ 127 int v=(locx+d[0][k]-1)*m+locy+d[1][k]; 128 if (dep[v]>dep[u]+1){ 129 dep[v]=dep[u]+1; 130 q[++ta]=v; 131 } 132 } 133 } 134 } 135 map[sx][sy]=1; 136 }
原文:http://www.cnblogs.com/ZXTLFDeAR/p/4805119.html