zoukankan      html  css  js  c++  java
  • 「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
      ",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
      ",ans[i]);
          return 0;
      }
      

    2019.4.12

  • 相关阅读:
    centos7安装zabbix4.2
    python3.x 基础三:文件IO
    python3.x 基础三:字符集问题
    python3.x 基础三:set集合
    python3.x 基础二:内置函数
    python3.x 基础一:dict字典
    python3.x 基础一:str字符串方法
    python3.x 基础一
    [leetcode]Path Sum
    [leetcode]Balanced Binary Tree
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10696999.html
Copyright © 2011-2022 走看看