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

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

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

 #include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
int n,m,a[],ans=-0x7fffffff;
int fin[],st[];
struct num{
int x1,x2;
num(){x1=x2=;}
num(int x,char o){
if(o=='v')x1=x,x2=;
else x1=,x2=x;
}
};
struct data{
char o,f;
num x,y;
int s1,s2;
}d[];
char getc(){
char ch=getchar();
while(ch!='v'&&ch!='c'&&ch!='i'&&ch!='s'&&ch!='+'&&ch!='-')
ch=getchar();
return ch;
}
void dfs(int x,int step){
if(x>n||x<){
if(a[]>ans){
for(int i=;i<step;i++)
fin[i]=st[i];
ans=a[];
}
return ;
}
if(d[x].o=='v'){
int now=d[x].y.x1?a[d[x].y.x1]:d[x].y.x2;
if(d[x].f=='+')a[d[x].x.x1]+=now;
else a[d[x].x.x1]-=now;
dfs(x+,step);
if(d[x].f=='+')a[d[x].x.x1]-=now;
else a[d[x].x.x1]+=now;
}
if(d[x].o=='i'){
int x1=d[x].x.x1?a[d[x].x.x1]:d[x].x.x2;
int x2=d[x].y.x1?a[d[x].y.x1]:d[x].y.x2;
if(x1<x2)dfs(d[x].s1,step);
else dfs(d[x].s2,step);
}
if(d[x].o=='s'){
st[step]=,dfs(d[x].s1,step+);
st[step]=,dfs(d[x].s2,step+);
}
}
int read(){
int a=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){a=a*+ch-'';ch=getchar();}
return a*f;
}
int main(){
freopen("train1.in","r",stdin);
freopen("train1.in","r",stdin);
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++){
d[i].o=getc();
if(d[i].o=='v'){
d[i].x=num(read(),'v');
d[i].f=getc();
d[i].y=num(read(),getc());
}
else if(d[i].o=='s'){
d[i].s1=read();
d[i].s2=read();
}
else if(d[i].o=='i'){
d[i].x=num(read(),getc());
d[i].y=num(read(),getc());
d[i].s1=read();
d[i].s2=read();
}
}
dfs(,);
for(int i=;fin[i];i++)
printf("%d\n",fin[i]);
return ;
}

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

 #include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
int n,m,a[],ans=-0x7fffffff;
int fin[],st[];
struct num{
int x1,x2;
num(){x1=x2=;}
num(int x,char o){
if(o=='v')x1=x,x2=;
else x1=,x2=x;
}
};
struct data{
char o,f;
num x,y;
int s1,s2;
}d[];
char getc(){
char ch=getchar();
while(ch!='v'&&ch!='c'&&ch!='i'&&ch!='s'&&ch!='+'&&ch!='-')
ch=getchar();
return ch;
}
void dfs(int x,int step,int pos){
if(x>(pos*)||x<=(pos-)*){
if(a[]>ans){
for(int i=;i<step;i++)
fin[i]=st[i];
ans=a[];
}
return ;
}
if(d[x].o=='v'){
int now=d[x].y.x1?a[d[x].y.x1]:d[x].y.x2;
if(d[x].f=='+')a[d[x].x.x1]+=now;
else a[d[x].x.x1]-=now;
dfs(x+,step,pos);
if(d[x].f=='+')a[d[x].x.x1]-=now;
else a[d[x].x.x1]+=now;
}
if(d[x].o=='i'){
int x1=d[x].x.x1?a[d[x].x.x1]:d[x].x.x2;
int x2=d[x].y.x1?a[d[x].y.x1]:d[x].y.x2;
if(x1<x2)dfs(d[x].s1,step,pos);
else dfs(d[x].s2,step,pos);
}
if(d[x].o=='s'){
st[step]=,dfs(d[x].s1,step+,pos);
st[step]=,dfs(d[x].s2,step+,pos);
}
}
int read(){
int a=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){a=a*+ch-'';ch=getchar();}
return a*f;
}
int main(){
freopen("train3.in","r",stdin);
freopen("train3.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++){
d[i].o=getc();
if(d[i].o=='v'){
d[i].x=num(read(),'v');
d[i].f=getc();
d[i].y=num(read(),getc());
}
else if(d[i].o=='s'){
d[i].s1=read();
d[i].s2=read();
}
else if(d[i].o=='i'){
d[i].x=num(read(),getc());
d[i].y=num(read(),getc());
d[i].s1=read();
d[i].s2=read();
}
}
for(int i=;i<=;i++){
ans=-0x7fffffff;
memset(fin,,sizeof fin);
memset(a,,sizeof a);
dfs((i-)*+,,i);
for(int i=;fin[i];i++)
printf("%d\n",fin[i]);
}
return ;
}

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

 #include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
int n,m,a[],ans=-0x7fffffff;
int fin[],st[];
struct num{
int x1,x2;
num(){x1=x2=;}
num(int x,char o){
if(o=='v')x1=x,x2=;
else x1=,x2=x;
}
};
struct data{
char o,f;
num x,y;
int s1,s2,id;
}d[];
char getc(){
char ch=getchar();
while(ch!='v'&&ch!='c'&&ch!='i'&&ch!='s'&&ch!='+'&&ch!='-')
ch=getchar();
return ch;
}
int read(){
int a=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){a=a*+ch-'';ch=getchar();}
return a*f;
}
int f[][],g[][],pp[];
int c[],w[],tot,pf[][],pg[][];
vector<int> pr[];
void dfs(int x,int y,int o){
if(!x)return ;
if(o==||y>=c[x])fin[x]=o;
else fin[x]=;
if(o==){
if(pf[x][y])dfs(pf[x][y],y+c[x],);
else dfs(x-,y+c[x],);
}
else{
if(pg[x][y])dfs(pg[x][y],y,);
else dfs(x-,y,);
}
}
int main(){
freopen("train6.in","r",stdin);
freopen("train6.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++){
d[i].o=getc();
if(d[i].o=='v'){
d[i].x=num(read(),'v');
d[i].f=getc();
d[i].y=num(read(),getc());
if(i==){d[i].id=;continue;}
if(d[i].x.x1==)c[++tot]=d[i].y.x2;
else w[tot]=d[i].y.x2;
d[i].id=tot;
}
else if(d[i].o=='s'){
pp[tot+]=i;
d[i].id=tot+;
d[i].s1=read();
d[i].s2=read();
}
else if(d[i].o=='i'){
d[i].id=tot+;
d[i].x=num(read(),getc());
d[i].y=num(read(),getc());
d[i].s1=read();
d[i].s2=read();
}
}
d[].id=tot+;
for(int i=;i<=tot;i++)
pr[d[d[pp[i]].s2].id].push_back(i);
memset(f,-0x3f,sizeof f);
f[][]=;
int p1,p2;
for(int i=;i<=tot;i++){
for(int j=c[i];j<=;j++){
f[i][j-c[i]]=f[i-][j]+w[i];
pf[i][j-c[i]]=;
for(int k=;k<pr[i].size();k++)if(g[pr[i][k]][j]+w[i]>f[i][j-c[i]]){
f[i][j-c[i]]=g[pr[i][k]][j]+w[i];
pf[i][j-c[i]]=pr[i][k];
}
if(f[i][j-c[i]]>ans){
ans=f[i][j-c[i]];
p1=i;p2=j-c[i];
}
}
for(int j=;j<=;j++){
g[i][j]=f[i-][j];
pg[i][j]=;
for(int k=;k<pr[i].size();k++)if(g[pr[i][k]][j]>g[i][j]){
g[i][j]=g[pr[i][k]][j];
pg[i][j]=pr[i][k];
}
}
}
dfs(p1,p2,);
for(int i=;i<=tot;i++)if(fin[i])printf("%d\n",fin[i]);
return ;
}

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

 #include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
int n,m,a[],ans=-0x7fffffff;
int fin[][],st[];
int f[][],g[][],pp[];
int c[],w[],tot,pf[][],pg[][];
vector<int> pr[];
struct num{
int x1,x2;
num(){x1=x2=;}
num(int x,char o){
if(o=='v')x1=x,x2=;
else x1=,x2=x;
}
};
struct data{
char o,f;
num x,y;
int s1,s2,id;
}d[];
char getc(){
char ch=getchar();
while(ch!='v'&&ch!='c'&&ch!='i'&&ch!='s'&&ch!='+'&&ch!='-')
ch=getchar();
return ch;
}
int be,en;
void dfs(int x,int step,int pos){
if(x>en||x<be){
if(a[]>w[pos]){
for(int i=;i<step;i++)
fin[pos][i]=st[i];
w[pos]=a[];
}
return ;
}
if(d[x].o=='v'){
int now=d[x].y.x1?a[d[x].y.x1]:d[x].y.x2;
if(d[x].f=='+')a[d[x].x.x1]+=now;
else a[d[x].x.x1]-=now;
dfs(x+,step,pos);
if(d[x].f=='+')a[d[x].x.x1]-=now;
else a[d[x].x.x1]+=now;
}
if(d[x].o=='i'){
int x1=d[x].x.x1?a[d[x].x.x1]:d[x].x.x2;
int x2=d[x].y.x1?a[d[x].y.x1]:d[x].y.x2;
if(x1<x2)dfs(d[x].s1,step,pos);
else dfs(d[x].s2,step,pos);
}
if(d[x].o=='s'){
st[step]=,dfs(d[x].s1,step+,pos);
st[step]=,dfs(d[x].s2,step+,pos);
}
}
int read(){
int a=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){a=a*+ch-'';ch=getchar();}
return a*f;
}
void dfs1(int x,int y,int o){
if(!x)return ;
if(o==||y>=c[x])fin[x][]=o;
else fin[x][]=;
if(o==){
if(pf[x][y])dfs1(pf[x][y],y+c[x],);
else dfs1(x-,y+c[x],);
}
else{
if(pg[x][y])dfs1(pg[x][y],y,);
else dfs1(x-,y,);
}
}
int main(){
freopen("train10.in","r",stdin);
freopen("train10.out","w",stdout);
scanf("%d%d",&n,&m);
memset(w,-0x3f,sizeof w);
for(int i=;i<=n;i++){
d[i].o=getc();
if(d[i].o=='v'){
d[i].x=num(read(),'v');
d[i].f=getc();
d[i].y=num(read(),getc());
if(i==){d[i].id=;continue;}
if(d[i].x.x1==){
c[tot]=d[i].y.x2;
be=i+;
}
d[i].id=tot;
}
else if(d[i].o=='s'){
d[i].s1=read();
d[i].s2=read();
d[i].id=tot;
if(!pp[tot])pp[tot]=i;
}
else if(d[i].o=='i'){
d[i].x=num(read(),getc());
d[i].y=num(read(),getc());
d[i].s1=read();
d[i].s2=read();
if(d[i].x.x1==){
if(tot){en=i-;dfs(be,,tot);}
tot++;
for(int j=i-;d[j].o=='i'&&d[j].s2==;j--)
d[j].id=tot;
}
d[i].id=tot;
}
}
en=n;
dfs(be,,tot);
for(int i=;i<=tot;i++)
pr[d[d[pp[i]].s2].id].push_back(i);
memset(f,-0x3f,sizeof f);
f[][]=;
int p1,p2;
for(int i=;i<=tot;i++){
for(int j=c[i];j<=;j++){
f[i][j-c[i]]=f[i-][j]+w[i];
pf[i][j-c[i]]=;
for(int k=;k<pr[i].size();k++)if(g[pr[i][k]][j]+w[i]>f[i][j-c[i]]){
f[i][j-c[i]]=g[pr[i][k]][j]+w[i];
pf[i][j-c[i]]=pr[i][k];
}
if(f[i][j-c[i]]>ans){
ans=f[i][j-c[i]];
p1=i;p2=j-c[i];
}
}
for(int j=;j<=;j++){
g[i][j]=f[i-][j];
pg[i][j]=;
for(int k=;k<pr[i].size();k++)if(g[pr[i][k]][j]>g[i][j]){
g[i][j]=g[pr[i][k]][j];
pg[i][j]=pr[i][k];
}
}
}
dfs1(p1,p2,);
for(int i=;i<=tot;i++)if(fin[i][]){
printf("%d\n",fin[i][]);
if(fin[i][]==){
for(int j=;fin[i][j];j++)
printf("%d\n",fin[i][j]);
}
}
return ;
}

提答,提答。

uoj123 【NOI2013】小Q的修炼的更多相关文章

  1. 「NOI2013」小 Q 的修炼 解题报告

    「NOI2013」小 Q 的修炼 第一次完整的做出一个提答,花了半个晚上+一个上午+半个下午 总体来说太慢了 对于此题,我认为的难点是观察数据并猜测性质和读入操作 我隔一会就思考这个sb字符串读起来怎 ...

  2. 【NOI2013】小Q的修炼

    题目链接:http://uoj.ac/problem/123 又开提答坑啦,要不是一定要讲题谁他妈要这样伤害自己 CASE 1,2 首先可以打一个通用暴力,用于模拟操作过程,对于每一个操作随机一个选择 ...

  3. HD4505小Q系列故事——电梯里的爱情

    Problem Description 细心的同事发现,小Q最近喜欢乘电梯上上下下,究其原因,也许只有小Q自己知道:在电梯里经常可以遇到他心中的女神HR. 电梯其实是个很暧昧的地方,只有在电梯里,小Q ...

  4. hdu4505小Q系列故事——电梯里的爱情

    小Q系列故事——电梯里的爱情 Time Limit: 300/100 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Tota ...

  5. 小Q系列故事——电梯里的爱情

    小Q系列故事——电梯里的爱情 Time Limit : 300/100ms (Java/Other)   Memory Limit : 65535/32768K (Java/Other) Total ...

  6. 平面直接坐标系线段相交问题(小Q(钟神)的问题)

    [问题描述] 小 Q 对计算几何有着浓厚的兴趣.他经常对着平面直角坐标系发呆,思考一些有趣的问题.今天,他想到了一个十分有意思的题目:首先,小 Q 会在?轴正半轴和?轴正半轴分别挑选?个点.随后,他将 ...

  7. hdu---(4515)小Q系列故事——世界上最遥远的距离(模拟题)

    小Q系列故事——世界上最遥远的距离 Time Limit: 500/200 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)T ...

  8. HDU-4515 小Q系列故事——世界上最遥远的距离

    小Q系列故事——世界上最遥远的距离 Time Limit: 500/200 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) ...

  9. 2013腾讯编程马拉松初赛第二场(3月22日) 小Q系列故事——为什么时光不能倒流 ---好水!!

    我以为我会是最坚强的那一个 我还是高估了自己 我以为你会是最无情的那一个 还是我贬低了自己 就算不能够在一起 我还是为你担心 就算你可能听不清 也代表我的心意 那北极星的眼泪 闪过你曾经的眼角迷离 那 ...

随机推荐

  1. 【转载】tomcat+nginx+redis实现均衡负载、session共享(二)

    今天我们接着说上次还没完成session共享的部分,还没看过上一篇的朋友可以先看下上次内容,http://www.cnblogs.com/zhrxidian/p/5432886.html. 1.red ...

  2. Golang中WaitGroup使用的一点坑

    Golang中WaitGroup使用的一点坑 Golang 中的 WaitGroup 一直是同步 goroutine 的推荐实践.自己用了两年多也没遇到过什么问题.直到一天午睡后,同事扔过来一段奇怪的 ...

  3. Android layout_margin 无效的解决办法

    http://www.aichengxu.com/view/31025 1.如果LinearLayout中使用Android:layout_marginRight不起作用,通过测试原来在android ...

  4. jvm垃圾回收(三)

    一.分代思想(年轻代.老年代.永久代): 1.一个新人(new对象)会优先在伊甸园(Eden区)出生,当伊甸园(Eden区)人口达到最大容量时,JVM会派MinorGC去看看哪些人还有价值 2.伊甸园 ...

  5. JS中$含义和用法

    原博客:https://www.cnblogs.com/jokerjason/p/7404649.html$在JS中本身只是一个符号而异,在JS里什么也不是.但在JS应用库JQUERY的作者将之做为一 ...

  6. Hi,这有一份风控体系建设干货

    互联网.移动互联网.云计算.大数据.人工智能.物联网.区块链等技术已经在人类经济生活中扮演越来越重要的角色,技术给人类带来各种便利的同时,很多企业也饱受"硬币"另一面的伤害,并且形 ...

  7. POST与PUT

    POST和PUT都是HTTP中客户端向服务器发送请求的方法 POST : 向指定资源提交数据,请求服务器进行处理(例如提交表单或者上传文件).数据被包含在请求本文中.这个请求可能会创建新的 资源或修改 ...

  8. Python并发编程之创建多线程的几种方法(二)

    大家好,并发编程 进入第二篇. 今天的内容会比较基础,主要是为了让新手也能无障碍地阅读,所以还是要再巩固下基础.学完了基础,你们也就能很顺畅地跟着我的思路理解以后的文章. 本文目录 学会使用函数创建多 ...

  9. Myeclipse+selenium2.0+Junit+TestNg环境搭建

    这周末把自动化的环境搭好了,在网上也百度了很多,现在分享下,希望大家少走一点歪路. 需要用到的安装包都在这个里面,自取: 链接:https://pan.baidu.com/s/10ohf757ztgN ...

  10. ubuntu 命令整合2

    通配符 * 匹配任意多个字符 ?匹配一个任意字符 示例:ls *.txt  rm -rf *.txt 文本编辑器 vi.vim 格式:vi 文件名 编辑 vi的三种工作模式 正常模式(启动进入的模式) ...