「NOI2013」小 Q 的修炼 解题报告
「NOI2013」小 Q 的修炼
第一次完整的做出一个提答,花了半个晚上+一个上午+半个下午
总体来说太慢了
对于此题,我认为的难点是观察数据并猜测性质和读入操作
我隔一会就思考这个sb字符串读起来怎么这么麻烦啊
首先可以发现,这个所有的选择都之后往后走,就是个topo图
task1,2,3
观察到数据有形如
s x x+11
v 3 + c y
v 4 + c y
v 5 + c y
v 6 + c y
v 7 + c y
v 8 + c y
v 9 + c y
v 10 + c y
v 11 + c y
v 12 + c y
之类的东西,而且每个这样的循环后面有一个这样的东西
i v 3 c 0 43 45
v 1 - v 3
i c 0 c 1 46 0
v 1 + v 3
v 3 - v 3
i v 4 c 0 48 50
v 1 - v 4
i c 0 c 1 51 0
v 1 + v 4
v 4 - v 4
...
发现这个就是把正的数据加到1上,负的不变并清空
这样就没法贪心或者dp了
然后我们又发现循环长度很小,直接爆搜就行了
代码搞丢了..
S_1 要讨论走哪个循环
S_2 直接爆搜
S_3 发现又很多组,分组爆搜
task4,5,6
最开始对变量2有一个正的初值
然后
s 5 8
v 2 - c 10
v 1 + c 22750
i c 0 c 1 8 0
i v 2 c 9 9 10
i c 0 c 1 14 0
循环节长这样
每次如果选择,会有一些跳转之类的
发现2的初值比较小而且后面只会减
考虑dp
\(dp_{i,j}\)第\(i\)行第\(2\)个变量的值是\(j\)的时候最大的\(1\)
然后模拟转移,记录路径就可以了
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
using std::max;
const int N=6010;
int n,m;
char op[5],t0[10],t1[10];
int x0,x1,x2,x2;
struct koito_yuu
{
int op,a,b,c;
koito_yuu(){}
koito_yuu(int Op,int A,int B,int C){op=Op,a=A,b=B,c=C;}
}yuu[N];
struct node
{
int i,j,cho;
node(){}
node(int I,int J,int Cho){i=I,j=J,cho=Cho;}
}pre[N][5010];
ll dp[N][5010];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%s",op);
if(op[0]=='s')
{
tim[++k]=i;
scanf("%d%d",&x1,&x2);
yuu[i]=koito_yuu(1,x1,x2,0);
}
else if(op[0]=='v')
{
scanf("%d%s%s%d",&x0,t0,t1,&x1);
yuu[i]=koito_yuu(2,x0,t1[0]=='+'?x1:-x1,0);
}
else
{
scanf("%s%d%s%d%d%d",t0,&x0,t1,&x1,&x2,&x3);
if(t0[0]=='c'&&t1[0]=='c') yuu[i]=koito_yuu(3,x2,0,0);
else if(t0[0]=='v'&&t1[0]=='c') yuu[i]=koito_yuu(4,x1,x2,x3);
}
}
memset(dp,-0x3f,sizeof dp);
int inf=dp[0][0];
dp[0][0]=0;
for(int i=1;i<=n;i++)
for(int j=0;j<=5000;j++)
if(dp[i-1][j]!=inf)
{
if(yuu[i].op==1)
{
int a=yuu[i].a,b=yuu[i].b;
if(dp[a][j]<dp[i][j])
{
pre[a][j]=node(i,j,1);
dp[a][j]=dp[i][j];
}
if(dp[b][j]<dp[i][j])
{
pre[b][j]=node(i,j,2);
dp[b][j]=dp[i][j];
}
}
else if(yuu[i].op==2)
{
int a=yuu[i].a,b=yuu[i].b;
if(a==1)
{
if(dp[i+1][j]<dp[i][j]+b)
{
pre[i+1][j]=node(i,j,0);
dp[i+1][j]=dp[i][j]+b;
}
}
else
{
int t=max(0,j+b);
if(dp[i+1][t]<dp[i][j])
{
pre[i+1][t]=node(i,j,0);
dp[i+1][t]=dp[i][j];
}
}
}
else if(yuu[i].op==3)
{
int a=yuu[i].a;
if(dp[a][j]<dp[i][j])
{
pre[a][j]=node(i,j,0);
dp[a][j]=dp[i][j];
}
}
else
{
int a=yuu[i].a,b=yuu[i].b,c=yuu[i].c;
if(j<a)
{
if(dp[b][j]<dp[i][j])
{
pre[b][j]=node(i,j,0);
dp[b][j]=dp[i][j];
}
}
else
{
if(dp[c][j]<dp[i][j])
{
pre[c][j]=node(i,j,0);
dp[c][j]=dp[i][j];
}
}
}
}
int tj=0;
for(int i=1;i<=5000;i++)
if(dp[n+1][tj]<dp[n+1][i])
tj=i;
int ti=n+1,cnt=0;
while(ti)
{
int tx=ti,ty=tj;
ti=pre[tx][ty].i,tj=pre[tx][ty].j;
if(pre[tx][ty].cho) ans[++cnt]=pre[tx][ty].cho;
}
for(int i=cnt;i;i--) printf("%d\n",ans[i]);
return 0;
}
4,5,6都是一样的
我本地跑6的时候居然开不下空间,还压了一会T_T
task7,8,9,10
这四个点就是前面的结合
最开始的时候有2控制跳转的东西
中间就是1,2,3点的循环
差不多175行一个周期
对周期压变量2的长度dp,每个周期里面爆搜
说起来简单,写起来还是很麻烦的
我这个代码要把in的最后几行删掉
Code:
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
using std::max;
using std::min;
const int N=35010;
int n,m;
char op[5],t0[10],t1[10];
int x0,x1,x2,x3;
struct koito_yuu
{
int op,a,b,c;
koito_yuu(){}
koito_yuu(int Op,int A,int B,int C){op=Op,a=A,b=B,c=C;}
}yuu[N];
struct node
{
int i,j,cho;
node(){}
node(int I,int J,int Cho){i=I,j=J,cho=Cho;}
}pre[N][1010];
ll dp[N][1010];
int Id[N],as[N][20],yuy[20][20],ct[N];
ll solve(int id,int L,int R)
{
int n=0;
for(int i=L;i<=R;i++)
{
if(yuu[i].op==1) ++n,yuy[n][0]=0;
if(yuu[i].op==2) yuy[n][++yuy[n][0]]=yuu[i].b;
if(yuu[i].op==3) break;
}
ll mx=-(1ll<<52);
ct[id]=n;
for(int s=0;s<1<<n;s++)
{
ll sum[20]={};
for(int i=1;i<=n;i++)
if(s>>i-1&1)
{
for(int j=1;j<=10;j++)
sum[j]+=yuy[i][j];
}
ll su=0;
for(int i=1;i<=10;i++) su+=sum[i]>0?sum[i]:-sum[i];
if(mx<su)
{
mx=su;
for(int i=1;i<=n;i++)
if(s>>i-1&1)
as[id][i]=1;
else
as[id][i]=2;
}
}
return mx;
}
int endro[N],k,ans[N];
int main()
{
freopen("train8.in","r",stdin);
freopen("train8.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%s",op);
if(op[0]=='s')
{
scanf("%d%d",&x1,&x2);
x2=min(x2,n+1);
yuu[i]=koito_yuu(1,x1,x2,0);
}
else if(op[0]=='v')
{
scanf("%d%s%s%d",&x0,t0,t1,&x1);
if(t1[0]=='c')
{
yuu[i]=koito_yuu(2,x0,t0[0]=='+'?x1:-x1,0);
}
else
{
yuu[i]=koito_yuu(3,x0,0,x1);
if(x0==12) endro[++k]=i;
}
}
else
{
scanf("%s%d%s%d%d%d",t0,&x0,t1,&x1,&x2,&x3);
x2=min(x2,n+1),x3=min(x3,n+1);
if(t0[0]=='c'&&t1[0]=='c') yuu[i]=koito_yuu(4,x2,0,0);
else if(t0[0]=='v'&&t1[0]=='c') yuu[i]=koito_yuu(5,x1,x2,x3);
}
}
memset(dp,-0x3f,sizeof dp);
dp[1][0]=0;
for(int i=1;i<=k;i++)
{
int tp;
for(int j=endro[i-1]+1;;j++)
if(yuu[j].op==1&&yuu[j].b-yuu[j].a==11)
{
tp=j-1;
break;
}
ll ad=solve(i,tp+1,endro[i]);
for(int l=endro[i-1]+1;l<=tp;l++)
for(int j=0;j<=1000;j++)
{
if(yuu[l].op==1)
{
int a=yuu[l].a,b=yuu[l].b;
if(dp[a][j]<dp[l][j])
{
dp[a][j]=dp[l][j];
pre[a][j]=node(l,j,1);
}
if(dp[b][j]<dp[l][j])
{
dp[b][j]=dp[l][j];
pre[b][j]=node(l,j,2);
}
}
else if(yuu[l].op==2)
{
int b=yuu[l].b;
int t=max(0,j+b);
if(dp[l+1][t]<dp[l][j])
{
dp[l+1][t]=dp[l][j];
pre[l+1][t]=node(l,j,0);
}
}
else if(yuu[l].op==4)
{
int a=yuu[l].a;
if(dp[a][j]<dp[l][j])
{
dp[a][j]=dp[l][j];
pre[a][j]=node(l,j,0);
}
}
else
{
int a=yuu[l].a,b=yuu[l].b,c=yuu[l].c;
if(j<a)
{
if(dp[b][j]<dp[l][j])
{
dp[b][j]=dp[l][j];
pre[b][j]=node(l,j,0);
}
}
else
{
if(dp[c][j]<dp[l][j])
{
dp[c][j]=dp[l][j];
pre[c][j]=node(l,j,0);
}
}
}
}
int s=tp+1,t=endro[i]+1;
Id[s]=i;
for(int j=0;j<=1000;j++)
if(dp[t][j]<dp[s][j]+ad)
{
dp[t][j]=dp[s][j]+ad;
pre[t][j]=node(s,j,3);
}
}
//9.22925584
//10.20218188
int tj=0;
for(int i=1;i<=1000;i++)
if(dp[n+1][tj]<dp[n+1][i])
tj=i;
int ti=n+1,cnt=0;
while(ti)
{
int tx=ti,ty=tj;
ti=pre[tx][ty].i,tj=pre[tx][ty].j;
if(pre[tx][ty].cho)
{
if(pre[tx][ty].cho==3)
{
int id=Id[ti];
for(int i=ct[id];i;i--) ans[++cnt]=as[id][i];
}
else
ans[++cnt]=pre[tx][ty].cho;
}
}
for(int i=cnt;i;i--) printf("%d\n",ans[i]);
return 0;
}
2019.4.12
「NOI2013」小 Q 的修炼 解题报告的更多相关文章
- 「SCOI2015」小凸想跑步 解题报告
「SCOI2015」小凸想跑步 最开始以为和多边形的重心有关,后来发现多边形的重心没啥好玩的性质 实际上你把面积小于的不等式列出来,发现是一次的,那么就可以半平面交了 Code: #include & ...
- 「SCOI2015」小凸解密码 解题报告
「SCOI2015」小凸解密码 题意:给一个环,定义一段连续的极长\(0\)串为\(0\)区间,定义一个位置的离一个\(0\)区间的距离为这个位置离这个区间中\(0\)的距离的最小值,每次询问一个位置 ...
- 「SCOI2015」小凸玩矩阵 解题报告
「SCOI2015」小凸玩矩阵 我好沙茶啊 把点当边连接行和列,在外面二分答案跑图的匹配就行了 我最开始二分方向搞反了,样例没过. 脑袋一抽,这绝壁要费用流,连忙打了个KM 然后wa了,一想这个不是完 ...
- 「SCOI2015」小凸玩密室 解题报告
「SCOI2015」小凸玩密室 虽然有心里在想一些奇奇怪怪的事情的原因,不过还是写太久了.. 不过这个题本身也挺厉害的 注意第一个被点亮的是任意选的,我最开始压根没注意到 \(dp_{i,j}\)代表 ...
- 【LOJ】#3020. 「CQOI2017」小 Q 的表格
#3020. 「CQOI2017」小 Q 的表格 这个的话求出来\(g = gcd(a,b)\) 会修改所有gcd为g的位置 我们要求\((g,g)\)这个位置的数一定是\(g^{2}\)的倍数 之后 ...
- 「SCOI2014」方伯伯运椰子 解题报告
「SCOI2014」方伯伯运椰子 可以看出是分数规划 然后我们可以看出其实只需要改变1的流量就可以了,因为每次改变要保证流量守恒,必须流成一个环,在正负性确定的情况下,变几次是无所谓的. 然后按照套路 ...
- 「SDOI2017」树点涂色 解题报告
「SDOI2017」树点涂色 我sb的不行了 其实一开始有一个类似动态dp的想法 每个点维护到lct树上到最浅点的颜色段数,然后维护一个\(mx_{0,1}\)也就是是否用虚儿子的最大颜色 用个set ...
- 「SCOI2014」方伯伯的 OJ 解题报告
「SCOI2014」方伯伯的 OJ 和列队有点像,平衡树点分裂维护即可 但是需要额外用个set之类的对编号查找点的位置 插入完了后记得splay,删除时注意特判好多东西 Code: #include ...
- 洛谷 P3698 [CQOI2017]小Q的棋盘 解题报告
P3698 [CQOI2017]小Q的棋盘 题目描述 小 Q 正在设计一种棋类游戏. 在小 Q 设计的游戏中,棋子可以放在棋盘上的格点中.某些格点之间有连线,棋子只能在有连线的格点之间移动.整个棋盘上 ...
随机推荐
- Nginx日志常用统计分析命令
IP相关统计 统计IP访问量(独立ip访问数量) awk '{print $1}' access.log | sort -n | uniq | wc -l 查看某一时间段的IP访问量(4-5点) gr ...
- HBase单机模式部署
1.上传&解压 2.设置环境变量 3.启用&检验 4.编辑hbase-env.sh 5.编辑hbase-site.xml 6.启动hbase 7.验证 8.启动hbase shell
- 关于MySQL集群的一些看法
作者:Gary Chen链接:https://zhuanlan.zhihu.com/p/20204156来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 市面上的招聘往往 ...
- SQL大全基本语法
一.基础 1.说明:创建数据库 CREATE DATABASE database-name 2.说明:删除数据库 drop database dbname 3.说明:备份sql server --- ...
- Windows下查看硬连接引用技术
Win10有了bash,可以方便的进入并用ll查看文件的硬连接数. 但是用powershell直接查看就比较麻烦了,比较曲折的找到了方法: fsutil hardlink list [filename ...
- Scrapy框架-Spider
目录 1. Spider 2.Scrapy源代码 2.1. Scrapy主要属性和方法 3.parse()方法的工作机制 1. Spider Spider类定义了如何爬取某个(或某些)网站.包括了爬取 ...
- 好程序员web前端分享如何理解JS的单线程
好程序员web前端分享如何理解JS单线程,JS本质是单线程的.也就是说,它并不能像JAVA语言那样,两个线程并发执行. 但我们平时看到的JS,分明是可以同时运作很多任务的,这又是怎么回事呢? 首先,J ...
- 性能测试中TPS上不去的几种原因浅析
转:https://www.cnblogs.com/imyalost/p/8309468.html 下面就说说压测中为什么TPS上不去的原因: 1.网络带宽 在压力测试中,有时候要模拟大量的用户请求, ...
- IDEA快捷建使用
因为以前使用的IDE工具是Eclipse,所以在公司中都是用IDEA的情况下,换成了IDEA,感觉是好用了很多. 其他快捷键: Ctrl+Shift + Enter,语句完成 “!”,否定完成,输入表 ...
- day09(垃圾回收机制)
1,复习 文件处理 1.操作文件的三步骤 -- 打开文件:硬盘的空间被操作系统持有 | 文件对象被应用程序持续 -- 操作文件:读写操作 -- 释放文件:释放操作系统对硬盘空间的持有 2.基础的读写 ...