NOIp 2011 Day1 解题报告

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,a[10010],b[10010],g[10010],k[10010],x,y;
10 
11 //solve//
12 int main(){
13     scanf("%d",&n);
14     for (int i=1;i<=n;++i){
15         scanf("%d%d%d%d",a+i,b+i,g+i,k+i);
16     }
17     scanf("%d%d",&x,&y);
18     int ans=-1;
19     for (int i=1;i<=n;++i){
20         if (a[i]<=x&&x<=a[i]+g[i]&&b[i]<=y&&y<=b[i]+k[i]){
21             ans=i;
22         }
23     }
24     printf("%d\n",ans);
25     return 0;
26 }
View Code

2.    选择客栈

用ST表求出区间最小值。

对于每组颜色相同的客栈建立双向链表,设sum[i]代表在i后面和i颜色相同的客栈的数量。外层枚举颜色,内层从左到右遍历链表,答案可以用乘法原理计算。具体请看代码。

复杂度O(NlogN+N)

网上好多大神用DP,然而比我这种暴力要复杂得多QAQ

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<algorithm>
 6 using namespace std;
 7 #define next asdfdfd
 8 //variable//
 9 int n,totc,maxp,col[200010],pri[200010];
10 int minst[200010][19];
11 int head[100],last[100],next[200010],pre[200010],totnext[200010];
12 
13 //function prototype//
14 void calc_minst(void);
15 int query(int,int);
16 void calc_totnext(void);
17 
18 //solve//
19 int main(){
20     scanf("%d%d%d",&n,&totc,&maxp);
21     for (int i=1;i<=n;++i){
22         scanf("%d%d",col+i,pri+i);
23         ++col[i];
24         if (!head[col[i]]){
25             head[col[i]]=last[col[i]]=i;
26         }else{
27             next[last[col[i]]]=i;
28             pre[i]=last[col[i]];
29             last[col[i]]=i;
30         }
31     }
32     calc_minst();
33     calc_totnext();
34     int ans=0ll;
35     for (int i=1;i<=totc;++i){
36         int t=0ll;
37         for (int u=head[i];next[u];u=next[u]){
38             ++t;
39             if (query(u,next[u])<=maxp){
40                 ans+=t*totnext[u];
41                 t=0;
42             }
43         }
44     }
45     cout<<ans<<endl;
46     return 0;
47 }
48 
49 void calc_totnext(){
50     for (int i=1;i<=totc;++i){
51         for (int u=pre[last[i]];u;u=pre[u]){
52             totnext[u]=totnext[next[u]]+1;
53         }
54     }
55 }
56 
57 void calc_minst(){
58     memset(minst,0x7f,sizeof minst);
59     for (int i=1;i<=n;++i){
60         minst[i][0]=pri[i];
61     }
62     for (int j=1;j<19;++j){
63         for (int i=1;i<=n;++i){
64             minst[i][j]=min(minst[i][j-1],(i+(1<<j-1)<=n?minst[i+(1<<j-1)][j-1]:0x7fffffff));
65         }
66     }
67 }
68 
69 int query(int l,int r){
70     int j=int((double)log(r-l+1)/log(2));
71     return min(minst[l][j],minst[r-(1<<j)+1][j]);
72 }
View Code

2.    mayan游戏

神一般的DFS搜索题,不过思路并不难。

根据字典序要求有以下几个剪枝:

  1. 当一个块的右边不空,只枚举这个块向右移,而不枚举另一个块向左移。
  2. 当一种颜色数量小于3时,剪枝。
  3. 不交换两个相同的块。
  4. 记录每次做出的操作,为后面判重。

其实有一种A*做法,但是以上就可以过全点。

(这个神题我在没有改缩进之前愣是写了200+行TAT)

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<iostream>
  5 using namespace std;
  6 
  7 //type//
  8 struct T{
  9     int x,y,ops;
 10 };
 11 
 12 //variable//
 13 int st[10][10],n;
 14 T ans[10];
 15 
 16 //function prototype//
 17 bool empty(void);
 18 void drop(void);
 19 bool clear(void);
 20 void dfs(int);
 21 
 22 //solve//
 23 int main(){
 24     scanf("%d",&n);
 25     for (int i=0;i<5;i++){
 26         for (int j=0;;j++){
 27             scanf("%d",&st[i][j]);
 28             if (!st[i][j]) break;
 29         }
 30     }
 31     dfs(1);
 32     printf("-1\n");
 33     return 0;
 34 }
 35 
 36 bool empty(){
 37     for (int i=0;i<5;i++)
 38         for (int j=0;j<7;j++)
 39             if (st[i][j]) return false;
 40     return true;
 41 }
 42 
 43 void drop(){
 44     int num[10][10];
 45     memset(num,-1,sizeof num);
 46     for (int x=0;x<5; x++){
 47         int h=0;
 48         for (int y=0;y<7;y++)
 49             if (st[x][y])
 50                 num[x][h++]=y;
 51     }
 52     for (int x=0;x<5;x++)
 53         for (int y=0;y<7;y++)
 54             st[x][y] = num[x][y]==-1?0:st[x][num[x][y]];
 55     return;
 56 }
 57 
 58 bool clear(){
 59     bool flag=0;
 60     for (int x=0;x<3;x++)
 61         for (int y=0;y<7;y++)
 62         if (st[x][y]){
 63             int x2;
 64             for (x2=x;x2+1<5&&st[x2+1][y]==st[x][y];x2++);
 65             if (x2-x>=2){
 66                 int tx;
 67                 for (tx=x;tx<=x2;tx++){
 68                     int Up=y,Dn=y;
 69                     while (Up+1<7&&st[tx][Up+1]==st[x][y]) Up++;
 70                     while (Dn-1>=0&&st[tx][Dn-1]==st[x][y]) Dn--;
 71                     if (Up-Dn>=2){
 72                         int ty;
 73                         for (ty=Dn;ty<=Up;ty++)
 74                             st[tx][ty]=0;
 75                     }
 76                 }
 77                 for (tx=x;tx<=x2;tx++)
 78                     st[tx][y]=0;
 79                 flag=1;
 80             }
 81         }
 82     for (int x=0;x<5;x++)
 83         for (int y=0;y<5;y++)
 84         if (st[x][y]){
 85             int y2;
 86             for (y2=y;y2+1<7&&st[x][y2+1]==st[x][y]; y2++);
 87             if (y2-y>=2){
 88                 int ty;
 89                 for (ty=y;ty<=y2;ty++){
 90                     int Lf=x,Ri=x;
 91                     while (Lf-1>=0&&st[Lf-1][ty]==st[x][y]) Lf--;
 92                     while (Ri+1<7&&st[Ri+1][ty]==st[x][y]) Ri++;
 93                     if (Ri-Lf>=2){
 94                         int tx;
 95                         for (tx=Lf;tx<=Ri;tx++)
 96                             st[tx][ty]=0;
 97                     }
 98                 }
 99                 for (ty=y;ty<=y2;ty++)
100                     st[x][ty]=0;
101                 flag=1;
102             }
103         }
104     if (flag) return true;
105     else return false;
106 }
107 
108 void dfs(int step){
109     if (step>n){
110         if (empty()){
111             for (int i=1;i<=n;i++){
112                 if (ans[i].ops)
113                     printf("%d %d %d\n",ans[i].x+1,ans[i].y,-1);
114                 else
115                     printf("%d %d %d\n",ans[i].x,ans[i].y,1);
116             }
117             exit(0);
118         }
119         return;
120     }
121     int sum[12];
122     memset(sum,0,sizeof sum);
123     for (int x=0;x<5;x++)
124         for (int y=0;y<7;y++)
125             sum[st[x][y]]++;
126     for (int i=1;i<=10;i++)
127         if (sum[i]!=0&&sum[i]<3) return;    
128     for (int x=0;x<4;x++)
129         for (int y=0;y<7;y++)
130         if (st[x][y]!=st[x+1][y]){
131             ans[step].x=x;
132             ans[step].y=y;
133             ans[step].ops=(!st[x][y]);
134             int temp[10][10];
135             memcpy(temp,st,sizeof temp);
136             swap(st[x][y],st[x+1][y]);
137             drop();
138             while(clear()) drop();
139             dfs(step+1);
140             ans[step].x=ans[step].y=ans[step].ops=0;
141             memcpy(st,temp,sizeof st);
142         }
143 }
View Code

 

posted @ 2015-09-20 18:55  DeAR3327  阅读(169)  评论(0编辑  收藏  举报