uoj123 【NOI2013】小Q的修炼
搞了一下午+半晚上。其实不是很难。
提答题重要的是要发现数据的特殊性质,然后根据不同数据写出不同的算法获得其对应的分数。
首先前两个测试点我们发现可以直接暴搜通过,事实上对于每个数据都暴搜加上一定的次数限制,都可以获得两分的好成绩。
#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的修炼的更多相关文章
- 「NOI2013」小 Q 的修炼 解题报告
「NOI2013」小 Q 的修炼 第一次完整的做出一个提答,花了半个晚上+一个上午+半个下午 总体来说太慢了 对于此题,我认为的难点是观察数据并猜测性质和读入操作 我隔一会就思考这个sb字符串读起来怎 ...
- 【NOI2013】小Q的修炼
题目链接:http://uoj.ac/problem/123 又开提答坑啦,要不是一定要讲题谁他妈要这样伤害自己 CASE 1,2 首先可以打一个通用暴力,用于模拟操作过程,对于每一个操作随机一个选择 ...
- HD4505小Q系列故事——电梯里的爱情
Problem Description 细心的同事发现,小Q最近喜欢乘电梯上上下下,究其原因,也许只有小Q自己知道:在电梯里经常可以遇到他心中的女神HR. 电梯其实是个很暧昧的地方,只有在电梯里,小Q ...
- hdu4505小Q系列故事——电梯里的爱情
小Q系列故事——电梯里的爱情 Time Limit: 300/100 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Tota ...
- 小Q系列故事——电梯里的爱情
小Q系列故事——电梯里的爱情 Time Limit : 300/100ms (Java/Other) Memory Limit : 65535/32768K (Java/Other) Total ...
- 平面直接坐标系线段相交问题(小Q(钟神)的问题)
[问题描述] 小 Q 对计算几何有着浓厚的兴趣.他经常对着平面直角坐标系发呆,思考一些有趣的问题.今天,他想到了一个十分有意思的题目:首先,小 Q 会在?轴正半轴和?轴正半轴分别挑选?个点.随后,他将 ...
- hdu---(4515)小Q系列故事——世界上最遥远的距离(模拟题)
小Q系列故事——世界上最遥远的距离 Time Limit: 500/200 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)T ...
- HDU-4515 小Q系列故事——世界上最遥远的距离
小Q系列故事——世界上最遥远的距离 Time Limit: 500/200 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) ...
- 2013腾讯编程马拉松初赛第二场(3月22日) 小Q系列故事——为什么时光不能倒流 ---好水!!
我以为我会是最坚强的那一个 我还是高估了自己 我以为你会是最无情的那一个 还是我贬低了自己 就算不能够在一起 我还是为你担心 就算你可能听不清 也代表我的心意 那北极星的眼泪 闪过你曾经的眼角迷离 那 ...
随机推荐
- 01_Linux学习_基础知识
学Linux就学命令行 === cd / 转到根目录,相对当前路径 cd dev 转到dev目录 whoami 查阅当前用户 pwd 查阅当前目录 ls 查阅当前目录下的目录和文件 === Linux ...
- properties类是Hashtable的子类
properties类是Hashtable的子类 增加了将Hashtable对象中的关键字保存到文件和从文件中读取关键字和值到Hashtable对象中的方法 Properties.store方法存储P ...
- oracle 查看表的索引信息
1.select * from user_indexes where table_name='PAMSODT0P02' 2.select * from user_ind_columns where ...
- git无法添加文件夹
如标题所示,在webapp下面创建了个空的pages文件夹,想着先提交一下,无奈怎么都提交不了,后来试着在文件夹下面随便添加了个文件就可以提交了, 也不知道是什么原因.
- eclipse乱码
eclipse乱码:Windows >general >Workspace UTF-8Windows >general >Editors >Text Editors &g ...
- [C#]使用 C# 编写自己的区块链挖矿算法
[C#] 使用 C# 编写自己区块链的挖矿算法 文章原文来自:Code your own blockchain mining algorithm in Go! ,原始文章通过 Go 语言来实现的,这里 ...
- Ubuntu硬盘空间清理
1.删除多余的安装下载文件: sudo aptitude autoclean sudo aptitude clean 2.删除多余的内核版本: sudo apt-get autoremove 4.去/ ...
- JavaScript函数节流和函数防抖之间的区别
一.概念解释 函数节流和函数防抖,两者都是优化高频率执行js代码的一种手段. 大家大概都知道旧款电视机的工作原理,就是一行行得扫描出色彩到屏幕上,然后组成一张张图片.由于肉眼只能分辨出一定频率的变 ...
- html5 标签在 IE 下使用
(function(){if(!/*@cc_on!@*/0)return;var e = "abbr,article,aside,audio,bb,canvas,datagrid,datal ...
- Setting up Latex-vim (or Latex-suite) plugin within macVim under Mac OSX Yosemite 2015-1-20 by congliu
1. Overview: Vim是命令行下的文本编辑程序,gVim是Vim的Linux下的图形化版本,macVim是Mac下的图形化版本 Latex-vim是vim写Latex文件时的插件 Skim是 ...