uoj123 【NOI2013】小Q的修炼

搞了一下午+半晚上。其实不是很难。

提答题重要的是要发现数据的特殊性质,然后根据不同数据写出不同的算法获得其对应的分数。

首先前两个测试点我们发现可以直接暴搜通过,事实上对于每个数据都暴搜加上一定的次数限制,都可以获得两分的好成绩。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <cmath>
 6 using namespace std;
 7 int n,m,a[105],ans=-0x7fffffff;
 8 int fin[1000500],st[1000500];
 9 struct num{
10     int x1,x2;
11     num(){x1=x2=0;}
12     num(int x,char o){
13         if(o=='v')x1=x,x2=0;
14         else x1=0,x2=x;
15     }
16 };
17 struct data{
18     char o,f;
19     num x,y;
20     int s1,s2;
21 }d[100500];
22 char getc(){
23     char ch=getchar();
24     while(ch!='v'&&ch!='c'&&ch!='i'&&ch!='s'&&ch!='+'&&ch!='-')
25         ch=getchar();
26     return ch;
27 }
28 void dfs(int x,int step){
29     if(x>n||x<1){
30         if(a[1]>ans){
31             for(int i=1;i<step;i++)
32                 fin[i]=st[i];
33             ans=a[1];
34         }
35         return ;
36     }
37     if(d[x].o=='v'){
38         int now=d[x].y.x1?a[d[x].y.x1]:d[x].y.x2;
39         if(d[x].f=='+')a[d[x].x.x1]+=now;
40         else a[d[x].x.x1]-=now;
41         dfs(x+1,step);
42         if(d[x].f=='+')a[d[x].x.x1]-=now;
43         else a[d[x].x.x1]+=now;
44     }
45     if(d[x].o=='i'){
46         int x1=d[x].x.x1?a[d[x].x.x1]:d[x].x.x2;
47         int x2=d[x].y.x1?a[d[x].y.x1]:d[x].y.x2;
48         if(x1<x2)dfs(d[x].s1,step);
49         else dfs(d[x].s2,step);
50     }
51     if(d[x].o=='s'){
52         st[step]=1,dfs(d[x].s1,step+1);
53         st[step]=2,dfs(d[x].s2,step+1);
54     }
55 }
56 int read(){
57     int a=0,f=1;char ch=getchar();
58     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
59     while(ch>='0'&&ch<='9'){a=a*10+ch-'0';ch=getchar();}
60     return a*f;
61 }
62 int main(){
63 freopen("train1.in","r",stdin);
64 freopen("train1.in","r",stdin);
65     scanf("%d%d",&n,&m);
66     for(int i=1;i<=n;i++){
67         d[i].o=getc();
68         if(d[i].o=='v'){
69             d[i].x=num(read(),'v');
70             d[i].f=getc();
71             d[i].y=num(read(),getc());
72         }
73         else if(d[i].o=='s'){
74             d[i].s1=read();
75             d[i].s2=read();
76         }
77         else if(d[i].o=='i'){
78             d[i].x=num(read(),getc());
79             d[i].y=num(read(),getc());
80             d[i].s1=read();
81             d[i].s2=read();
82         }
83     }
84     dfs(1,1);
85     for(int i=1;fin[i];i++)
86         printf("%d\n",fin[i]);
87     return 0;
88 }
View Code

对于第三个测试点,我们可以发现这其实是分成了好多独立的块,长度是170,我们发现,在块内有不多的决策点,然后块的末尾会将所有变量都加给1,然后清零,所以我们可以每个块内暴搜,然后合并起来。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <cmath>
 6 using namespace std;
 7 int n,m,a[105],ans=-0x7fffffff;
 8 int fin[1000500],st[1000500];
 9 struct num{
10     int x1,x2;
11     num(){x1=x2=0;}
12     num(int x,char o){
13         if(o=='v')x1=x,x2=0;
14         else x1=0,x2=x;
15     }
16 };
17 struct data{
18     char o,f;
19     num x,y;
20     int s1,s2;
21 }d[100500];
22 char getc(){
23     char ch=getchar();
24     while(ch!='v'&&ch!='c'&&ch!='i'&&ch!='s'&&ch!='+'&&ch!='-')
25         ch=getchar();
26     return ch;
27 }
28 void dfs(int x,int step,int pos){
29     if(x>(pos*170)||x<=(pos-1)*170){
30         if(a[1]>ans){
31             for(int i=1;i<step;i++)
32                 fin[i]=st[i];
33             ans=a[1];
34         }
35         return ;
36     }
37     if(d[x].o=='v'){
38         int now=d[x].y.x1?a[d[x].y.x1]:d[x].y.x2;
39         if(d[x].f=='+')a[d[x].x.x1]+=now;
40         else a[d[x].x.x1]-=now;
41         dfs(x+1,step,pos);
42         if(d[x].f=='+')a[d[x].x.x1]-=now;
43         else a[d[x].x.x1]+=now;
44     }
45     if(d[x].o=='i'){
46         int x1=d[x].x.x1?a[d[x].x.x1]:d[x].x.x2;
47         int x2=d[x].y.x1?a[d[x].y.x1]:d[x].y.x2;
48         if(x1<x2)dfs(d[x].s1,step,pos);
49         else dfs(d[x].s2,step,pos);
50     }
51     if(d[x].o=='s'){
52         st[step]=1,dfs(d[x].s1,step+1,pos);
53         st[step]=2,dfs(d[x].s2,step+1,pos);
54     }
55 }
56 int read(){
57     int a=0,f=1;char ch=getchar();
58     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
59     while(ch>='0'&&ch<='9'){a=a*10+ch-'0';ch=getchar();}
60     return a*f;
61 }
62 int main(){
63 freopen("train3.in","r",stdin);
64 freopen("train3.out","w",stdout);
65     scanf("%d%d",&n,&m);
66     for(int i=1;i<=n;i++){
67         d[i].o=getc();
68         if(d[i].o=='v'){
69             d[i].x=num(read(),'v');
70             d[i].f=getc();
71             d[i].y=num(read(),getc());
72         }
73         else if(d[i].o=='s'){
74             d[i].s1=read();
75             d[i].s2=read();
76         }
77         else if(d[i].o=='i'){
78             d[i].x=num(read(),getc());
79             d[i].y=num(read(),getc());
80             d[i].s1=read();
81             d[i].s2=read();
82         }
83     }
84     for(int i=1;i<=200;i++){
85         ans=-0x7fffffff;
86         memset(fin,0,sizeof fin);
87         memset(a,0,sizeof a);
88         dfs((i-1)*170+1,1,i);
89         for(int i=1;fin[i];i++)
90             printf("%d\n",fin[i]);
91     }
92     return 0;
93 }
View Code

对于456个测试点,我们发现只有两个变量,相当于是用钱买成就,于是我们可以做一个简单的dp,注意56两个点不一定跳到后面相邻的那个,所以又多了不少细节。我的f[i][j]表示在i处买完剩了j元钱的答案,g表示不在这里买。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <cmath>
  6 #include <vector>
  7 using namespace std;
  8 int n,m,a[105],ans=-0x7fffffff;
  9 int fin[1000500],st[1000500];
 10 struct num{
 11     int x1,x2;
 12     num(){x1=x2=0;}
 13     num(int x,char o){
 14         if(o=='v')x1=x,x2=0;
 15         else x1=0,x2=x;
 16     }
 17 };
 18 struct data{
 19     char o,f;
 20     num x,y;
 21     int s1,s2,id;
 22 }d[100500];
 23 char getc(){
 24     char ch=getchar();
 25     while(ch!='v'&&ch!='c'&&ch!='i'&&ch!='s'&&ch!='+'&&ch!='-')
 26         ch=getchar();
 27     return ch;
 28 }
 29 int read(){
 30     int a=0,f=1;char ch=getchar();
 31     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 32     while(ch>='0'&&ch<='9'){a=a*10+ch-'0';ch=getchar();}
 33     return a*f;
 34 }
 35 int f[2050][10050],g[2050][10050],pp[2050];
 36 int c[2050],w[2050],tot,pf[2050][10050],pg[2050][10050];
 37 vector<int> pr[2050];
 38 void dfs(int x,int y,int o){
 39     if(!x)return ;
 40     if(o==1||y>=c[x])fin[x]=o;
 41     else fin[x]=0;
 42     if(o==1){
 43         if(pf[x][y])dfs(pf[x][y],y+c[x],2);
 44         else dfs(x-1,y+c[x],1);
 45     }
 46     else{
 47         if(pg[x][y])dfs(pg[x][y],y,2);
 48         else dfs(x-1,y,1);
 49     }
 50 }
 51 int main(){
 52 freopen("train6.in","r",stdin);
 53 freopen("train6.out","w",stdout);
 54     scanf("%d%d",&n,&m);
 55     for(int i=1;i<=n;i++){
 56         d[i].o=getc();
 57         if(d[i].o=='v'){
 58             d[i].x=num(read(),'v');
 59             d[i].f=getc();
 60             d[i].y=num(read(),getc());
 61             if(i==1){d[i].id=0;continue;}
 62             if(d[i].x.x1==2)c[++tot]=d[i].y.x2;
 63             else w[tot]=d[i].y.x2;
 64             d[i].id=tot;
 65         }
 66         else if(d[i].o=='s'){
 67             pp[tot+1]=i;
 68             d[i].id=tot+1;
 69             d[i].s1=read();
 70             d[i].s2=read();
 71         }
 72         else if(d[i].o=='i'){
 73             d[i].id=tot+1;
 74             d[i].x=num(read(),getc());
 75             d[i].y=num(read(),getc());
 76             d[i].s1=read();
 77             d[i].s2=read();
 78         }
 79     }
 80     d[12002].id=tot+1;
 81     for(int i=1;i<=tot;i++)
 82         pr[d[d[pp[i]].s2].id].push_back(i);
 83     memset(f,-0x3f,sizeof f);
 84     f[0][10000]=0;
 85     int p1,p2;
 86     for(int i=1;i<=tot;i++){
 87         for(int j=c[i];j<=10000;j++){
 88             f[i][j-c[i]]=f[i-1][j]+w[i];
 89             pf[i][j-c[i]]=0;
 90             for(int k=0;k<pr[i].size();k++)if(g[pr[i][k]][j]+w[i]>f[i][j-c[i]]){
 91                 f[i][j-c[i]]=g[pr[i][k]][j]+w[i];
 92                 pf[i][j-c[i]]=pr[i][k];
 93             }
 94             if(f[i][j-c[i]]>ans){
 95                 ans=f[i][j-c[i]];
 96                 p1=i;p2=j-c[i];
 97             }
 98         }
 99         for(int j=0;j<=10000;j++){
100             g[i][j]=f[i-1][j];
101             pg[i][j]=0;
102             for(int k=0;k<pr[i].size();k++)if(g[pr[i][k]][j]>g[i][j]){
103                 g[i][j]=g[pr[i][k]][j];
104                 pg[i][j]=pr[i][k];
105             }
106         }
107     }
108     dfs(p1,p2,1);
109     for(int i=1;i<=tot;i++)if(fin[i])printf("%d\n",fin[i]);
110     return 0;
111 }
View Code

最后四个点我们发现明显就是暴搜和dp拼起来,我们对于每个块内搜出他的贡献,然后和上面一样dp就好了。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <cmath>
  6 #include <vector>
  7 using namespace std;
  8 int n,m,a[105],ans=-0x7fffffff;
  9 int fin[2050][1050],st[1050];
 10 int f[2050][10050],g[2050][10050],pp[2050];
 11 int c[2050],w[2050],tot,pf[2050][10050],pg[2050][10050];
 12 vector<int> pr[2050];
 13 struct num{
 14     int x1,x2;
 15     num(){x1=x2=0;}
 16     num(int x,char o){
 17         if(o=='v')x1=x,x2=0;
 18         else x1=0,x2=x;
 19     }
 20 };
 21 struct data{
 22     char o,f;
 23     num x,y;
 24     int s1,s2,id;
 25 }d[100500];
 26 char getc(){
 27     char ch=getchar();
 28     while(ch!='v'&&ch!='c'&&ch!='i'&&ch!='s'&&ch!='+'&&ch!='-')
 29         ch=getchar();
 30     return ch;
 31 }
 32 int be,en;
 33 void dfs(int x,int step,int pos){
 34     if(x>en||x<be){
 35         if(a[1]>w[pos]){
 36             for(int i=1;i<step;i++)
 37                 fin[pos][i]=st[i];
 38             w[pos]=a[1];
 39         }
 40         return ;
 41     }
 42     if(d[x].o=='v'){
 43         int now=d[x].y.x1?a[d[x].y.x1]:d[x].y.x2;
 44         if(d[x].f=='+')a[d[x].x.x1]+=now;
 45         else a[d[x].x.x1]-=now;
 46         dfs(x+1,step,pos);
 47         if(d[x].f=='+')a[d[x].x.x1]-=now;
 48         else a[d[x].x.x1]+=now;
 49     }
 50     if(d[x].o=='i'){
 51         int x1=d[x].x.x1?a[d[x].x.x1]:d[x].x.x2;
 52         int x2=d[x].y.x1?a[d[x].y.x1]:d[x].y.x2;
 53         if(x1<x2)dfs(d[x].s1,step,pos);
 54         else dfs(d[x].s2,step,pos);
 55     }
 56     if(d[x].o=='s'){
 57         st[step]=1,dfs(d[x].s1,step+1,pos);
 58         st[step]=2,dfs(d[x].s2,step+1,pos);
 59     }
 60 }
 61 int read(){
 62     int a=0,f=1;char ch=getchar();
 63     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 64     while(ch>='0'&&ch<='9'){a=a*10+ch-'0';ch=getchar();}
 65     return a*f;
 66 }
 67 void dfs1(int x,int y,int o){
 68     if(!x)return ;
 69     if(o==1||y>=c[x])fin[x][0]=o;
 70     else fin[x][0]=0;
 71     if(o==1){
 72         if(pf[x][y])dfs1(pf[x][y],y+c[x],2);
 73         else dfs1(x-1,y+c[x],1);
 74     }
 75     else{
 76         if(pg[x][y])dfs1(pg[x][y],y,2);
 77         else dfs1(x-1,y,1);
 78     }
 79 }
 80 int main(){
 81 freopen("train10.in","r",stdin);
 82 freopen("train10.out","w",stdout);
 83     scanf("%d%d",&n,&m);
 84     memset(w,-0x3f,sizeof w);
 85     for(int i=1;i<=n;i++){
 86         d[i].o=getc();
 87         if(d[i].o=='v'){
 88             d[i].x=num(read(),'v');
 89             d[i].f=getc();
 90             d[i].y=num(read(),getc());
 91             if(i==1){d[i].id=0;continue;}
 92             if(d[i].x.x1==2){
 93                 c[tot]=d[i].y.x2;
 94                 be=i+1;
 95             }
 96             d[i].id=tot;
 97         }
 98         else if(d[i].o=='s'){
 99             d[i].s1=read();
100             d[i].s2=read();
101             d[i].id=tot;
102             if(!pp[tot])pp[tot]=i;
103         }
104         else if(d[i].o=='i'){
105             d[i].x=num(read(),getc());
106             d[i].y=num(read(),getc());
107             d[i].s1=read();
108             d[i].s2=read();
109             if(d[i].x.x1==2){
110                 if(tot){en=i-1;dfs(be,1,tot);}
111                 tot++;
112                 for(int j=i-1;d[j].o=='i'&&d[j].s2==0;j--)
113                     d[j].id=tot;
114             }
115             d[i].id=tot;
116         }
117     }
118     en=n;
119     dfs(be,1,tot);
120     for(int i=1;i<=tot;i++)
121         pr[d[d[pp[i]].s2].id].push_back(i);
122     memset(f,-0x3f,sizeof f);
123     f[0][1000]=0;
124     int p1,p2;
125     for(int i=1;i<=tot;i++){
126         for(int j=c[i];j<=1000;j++){
127             f[i][j-c[i]]=f[i-1][j]+w[i];
128             pf[i][j-c[i]]=0;
129             for(int k=0;k<pr[i].size();k++)if(g[pr[i][k]][j]+w[i]>f[i][j-c[i]]){
130                 f[i][j-c[i]]=g[pr[i][k]][j]+w[i];
131                 pf[i][j-c[i]]=pr[i][k];
132             }
133             if(f[i][j-c[i]]>ans){
134                 ans=f[i][j-c[i]];
135                 p1=i;p2=j-c[i];
136             }
137         }
138         for(int j=0;j<=1000;j++){
139             g[i][j]=f[i-1][j];
140             pg[i][j]=0;
141             for(int k=0;k<pr[i].size();k++)if(g[pr[i][k]][j]>g[i][j]){
142                 g[i][j]=g[pr[i][k]][j];
143                 pg[i][j]=pr[i][k];
144             }
145         }
146     }
147     dfs1(p1,p2,1);
148     for(int i=1;i<=tot;i++)if(fin[i][0]){
149         printf("%d\n",fin[i][0]);
150         if(fin[i][0]==1){
151             for(int j=1;fin[i][j];j++)
152                 printf("%d\n",fin[i][j]);
153         }
154     }
155     return 0;
156 }
View Code

提答,提答。

posted @ 2018-05-02 19:37  Ren_Ivan  阅读(...)  评论(... 编辑 收藏