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 }
对于第三个测试点,我们可以发现这其实是分成了好多独立的块,长度是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 }
对于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 }
最后四个点我们发现明显就是暴搜和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 }
提答,提答。
人生如梦亦如幻 朝如晨露暮如霞。