【2019.1.24】 搜索,动规 经典题目体验赛

T1 工作依赖

  • 题目描述(Description

  2008年,奥运会将在中国举行。众所周知举办奥运会是一个庞大的工程,有许多准备工作要做,而这些工作也是要分先后、存在依赖关系的。比如我们说工作2依赖于工作1,意思是说在工作2开始做之前要必须结束工作1。我们假设,在一个时刻只有一个工作在进行,而且每样工作所依赖的其它工作不会超过10个。

  • 输入文件(job.in):

  第一行有两个整数N(0<=N<=10000)和M。所有工作从1到N编号。你需要计算第M个工作的最早结束时间。

接下来N行每行描述一个工作,第1行描述工作1,第二行描述工作2,……,以此类推。每行包含几个正整数,第i行的第1个整数是完成第i个工作需要的时间T(0<T<=100),第i行的其余数字是第i个工作所依赖的其它工作编号。我们保证不会出现循环依赖。

  • 输出文件(job.out):

  一个整数:工作M的最早结束时间。

  • 样例(Sample):

Sample Input Case 1:

2 2

3

2 1

Sample Output Case 1:

5

 

Sample Input Case 2:

3 3

3

2 1

4 1 2

Sample Output Case 2:

9

我的零分代码 (我不知道把零分代码贴上来干什么)

 1 /*
 2 id:gww
 3 language:
 4 啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊 
 5 */
 6 #include<bits/stdc++.h>
 7 using namespace std;
 8 const int N=10000+5;
 9 const int inf=0x3f3f3f3f;
10 int n,m,ti[N],dep[N][12],c[N],f[N][12];
11 bool vis[N][12];
12 int read()
13 {
14     int x=0,w=0;char ch=0;
15     while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
16     while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
17     return w?-x:x;
18 }
19  
20 void dp(int u,int gs)
21 {
22     if(gs==c[u]) return;
23     for(int i=1;i<=c[u];i++)
24     {
25         int v=dep[u][i];
26         if(vis[u][i]==1) continue;
27         if(f[u][gs+1]>(f[u][gs]+ti[v]))
28         {
29             f[u][gs+1]=f[u][gs]+ti[v];
30             vis[u][i]=1;
31             dp(u,gs+1); 
32         }
33     }
34 }
35  
36 void clean()
37 {
38     memset(dep,0,sizeof(dep));
39     memset(c,0,sizeof(c));
40     memset(f,inf,sizeof(f));
41     memset(vis,0,sizeof(vis));
42 }
43  
44 int main()
45 {
46     n=read(),m=read();
47     clean();
48     char a[210];
49     for(int i=1;i<=n;i++)
50     {
51         memset(a,0,sizeof(a));
52         gets(a);
53         int la=strlen(a),cnt=0;
54         ti[i]=a[0]-'0';
55         for(int j=1;j<=la;j++)
56         if(a[j]>='0'&&a[j]<='9')
57         dep[i][++cnt]=a[j]-'0';
58     }
59     for(int i=1;i<=n;i++)     
60     if(dep[i][1]!=0)
61     for(int j=1;j<=10;j++)
62     if(dep[i][j]!=0)
63     c[i]++;
64     for(int i=1;i<=n;i++)//初始化 
65     f[i][0]=ti[i];
66     dp(m,0);
67     printf("%d",f[m][c[m]]);
68     return 0;
69 }
View Code

用昨天做时间复杂度学到的 一行一行用字符读然后判断,然后就爆炸了QAQ!!!我也不晓得为什么,它说我使用了系统禁止的操作系统调用。我哪敢啊!!

1 for(int i=1;i<=n;i++)
2 {
3     gets(a);
4     int la=strlen(a),cnt=0;
5     ti[i]=a[0]-'0';
6     for(int j=2;j<=la;j++)
7     if(a[j]>='0'&&a[j]<='9')
8     add(i,a[j]-'0');
9 }
爆炸输入

欧阳说是动规就满脑子动规动规动规,然后真没想到去搜索,搞了一堆奇奇怪怪的东西,自以为对了结果呵呵,果然还是我太垃圾了

输入就比较玄学,反正我写的都爆炸,贼难受

 1 /*
 2 id:gww
 3 language:
 4 啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊 
 5 */
 6 #include<bits/stdc++.h>
 7 using namespace std;
 8 const int N=10000+10;
 9 const int inf=0x3f3f3f3f;
10 int n,m,ti[N],ans=0;
11 int head[100000+55],cnt=0;
12 bool vis[N];
13 int read()
14 {
15     int x=0,w=0;char ch=0;
16     while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
17     while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
18     return w?-x:x;
19 }
20 
21 struct lxyy
22 {
23     int v,nxt;
24 }e[100000+55];
25 void add(int u,int v)
26 {
27     e[++cnt].v=v;
28     e[cnt].nxt=head[u];
29     head[u]=cnt;
30 }
31 
32 void clean()
33 {
34     memset(vis,0,sizeof(vis));
35     memset(head,0,sizeof(head));
36 }
37 
38 void dfs(int nw)
39 {
40     ans+=ti[nw];
41     vis[nw]=1;
42     for(int i=head[nw];i!=0;i=e[i].nxt)
43     {
44         int v=e[i].v;
45         if(vis[v]==0)
46         dfs(v);
47     }
48 }
49 
50 int main()
51 {
52     n=read(),m=read();
53     clean();
54        char a[2000];
55     for(int i=1;i<=n;i++)
56     {
57         scanf("%d",ti+i);
58         while(getchar()==' ') 
59         {
60             int x;
61             scanf("%d",&x);
62             add(i,x);
63         }
64     }
65     dfs(m);
66     printf("%d",ans);
67     return 0;
68 }
100昏

然后是大佬用isdigit判断的输入

 1     for(int i=1;i<=n;i++){
 2      
 3         string s;int x=0;
 4         scanf("%d",&t[i]);
 5         getline(cin,s);
 6         for(int j=0;j<=s.length();j++)
 7         {
 8             if(!isdigit(s[j]))
 9             {
10                 if(x!=0)
11                 {
12                     add(i,x);
13                     x=0;
14                 }
15                 continue;
16             }
17             else x=x*10+s[j]-'0';
18         }
19     }
dalao's

T2 英雄

  • 题目描述(Description):

  城堡迷宫由N×M个格子组成,英雄Mario玛丽奥要在城堡迷宫中从起始点移动到目标点去拯救被怪物掳去的公主,他每一步只能从当前所在的格子移动到相邻的4个格子之一,而且不能移出城堡的范围,走一步需要1秒的时间。

  城堡中某些格子里面有弹簧,每个弹簧具有特定的能量K,不同弹簧的K值不一定相同。如果Mario跳到一个有弹簧的格子,他就会继续向前跳K个格子或者被墙所阻挡无法继续向前,这个时间忽略不计。

10

 

 

 

 

 

 

 

 

 

 

◎:Mario  ★:公主   ▲:弹簧

示例一:Mario现所在位置是(2,8),有一个弹簧在(2,7),能量值为5,则Mario只需向左走一步,就会被弹到(2,2),从(2,8)到(2,2)Mario只需一步,即1秒。

示例二:Mario现所在位置是(2,8),有一个弹簧在(2,7),能量值为10,则Mario只需向左走一步,就会被弹到(2,1),从(2,8)到(2,1)Mario只需一步,即1秒。

9

 

 

 

 

 

 

 

 

 

 

8

 

 

 

 

 

 

 

 

 

 

7

 

 

 

 

 

 

 

 

 

6

 

 

 

 

 

 

 

 

 

 

5

 

 

 

 

 

 

 

 

 

 

4

 

 

 

 

 

 

 

 

 

 

3

 

 

 

 

 

 

 

 

 

 

2

 

 

 

 

 

 

 

 

1

 

 

 

 

 

 

 

 

 

 

 

1

2

3

4

5

6

7

8

9

10

 

请你计算Mario从起始点到达目标点(公主位置)需要的最短时间,如果不能到达,输出“Impossible”。

  • 输入文件(hero.in):

  第一行,两个整数,N和M(3<=N,M<=100),分别表示城堡的行和列。

  第二行,一个非负整数K,表示弹簧的数量。接下来K行,每行含3个正整数——X,Y,P。其中X,Y是弹簧的坐标(2<=X<=N-1,2<=Y<=M-1),P是该弹簧的能量。

接下来最后两行,第一行是Mario的坐标,第二行是公主的坐标。

  注意:输入文件保证没有一个弹簧是挨着城堡围墙的。

  • 输出文件(hero.out):

  输出Mario从初始位置到达公主所在位置需要的最短时间(秒)。如果不能到达,则输出“Impossible”。(引号不需输出)

  • 样例(Sample):

Sample Input Case 1:

10 10

1

2 7 5

2 8

1 1

Sample Output Case 1:

3

就很难受,被第一题冲昏了头脑,然后程序写是写出来了,脑子昏昏沉沉的弄不清那个弹簧往哪弹就没继续想,太难受了

就和骑士遍历差不多,只是多了一个弹簧

啊啊啊啊就是没搞懂那个弹簧怎么弹,向前弹不是向上啊啊啊,是向来时的方向弹,我这就滚回去学语文

还要感谢这道题,我总是错一堆玄学错误 就很快乐?? 我还有killed

  • Segmentation fault:段错误,检查是否有数组越界,指针异常,访问到不应该访问的内存区域
  • Killed:进程因为内存或时间原因被杀死,检查是否有死循环
  • A Not allowed system call: runid:18795 :使用了系统禁止的操作系统调用,看看是否越权访问了文件或进程等资源。
  • CALLID:20:可能存在数组越界,检查题目描述的数据量与所申请数组大小关系

一道搜索我能写几个小时也是牛逼?就很难受 这搜索的味道竟该死的甜美

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=100+10;
 4 const int inf=0x3f3f3f3f;
 5 int n,m,k,ex,ey,sx,sy;
 6 int mp[N][N];
 7 int dx[4]={0,0,-1,1};
 8 int dy[4]={-1,1,0,0};
 9 bool vis[N][N];
10 int read()
11 {
12     int x=0,w=0;char ch=0;
13     while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
14     while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
15     return w?-x:x;
16 }
17 struct lxyy
18 {
19     int x,y,ti;
20 };
21 
22 queue<lxyy> q;
23 void dfs()
24 {
25     lxyy a;
26     a.x=sx,a.y=sy,a.ti=0;
27     q.push(a);
28     while(!q.empty())
29     {
30         lxyy b=q.front();q.pop();
31         for(int i=0;i<=3;i++)
32         {
33             lxyy c;c.ti=b.ti+1;
34             int nx=b.x+dx[i],ny=b.y+dy[i];
35             if(ny<1||nx<1||nx>n||ny>m) continue;
36             int k=mp[nx][ny];
37             while(k)
38             {
39                 //if(i==0) c.y=max(1,c.y-k); if(i==1) c.y=min(n,c.y+k);//40                 //if(i==2) c.x=max(1,c.x-k); if(i==3) c.x=min(m,c.x+k);//
41                 ny+=(dy[i]*k);nx+=(dx[i]*k);
42                 if(ny>n) ny=n;if(ny<1) ny=1;
43                 if(nx>m) c.x=m;if(nx<1) nx=1;
44                 k=mp[nx][ny];
45             }
46             if(vis[nx][ny]) continue;
47             if(nx==ex&&ny==ey) {printf("%d",c.ti);return;}
48             c.x=nx,c.y=ny;
49             vis[nx][ny]=1;q.push(c);
50         }
51     }
52     printf("Impossible");
53     return ;
54 }
55 
56 int main()
57 {
58     memset(mp,0,sizeof(mp));
59     n=read(),m=read(),k=read();
60     for(int i=1;i<=k;i++)
61     {
62         int x=read(),y=read(),w=read();
63         mp[x][y]=w;
64     }
65     sx=read(),sy=read(),ex=read(),ey=read();
66     dfs();
67     return 0;
68  } 
75昏 被killed的程序

我已经改死了,几乎改的和大佬的一样才过的,大概这就是命???改一晚上 就很难受我选择死亡

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int dx[4]={0,0,1,-1};
 4 const int dy[4]={1,-1,0,0};
 5 const int N=105;
 6 int n,m,k,ex,ey,sx,sy;
 7 int mp[N][N];
 8 bool vis[N][N]; 
 9 struct node
10 {
11     int x,y;    
12     int step;
13 }start; 
14 int read()
15 {
16     int x=0,w=0;char ch=0;
17     while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
18     while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
19     return w?-x:x;
20 }
21 
22 queue <node> q;
23 void bfs()
24 {   
25     node a; 
26     a.x=sx,a.y=sy,a.step=0;    
27     q.push(a);    
28     while(!q.empty())    
29     {        
30         node b=q.front();q.pop();        
31         for(int i=0;i<=3;i++)        
32         {    
33             node c;            
34             c.x=b.x+dx[i];c.y=b.y+dy[i];            
35             c.step=b.step+1;            
36             if(c.x<1||c.x>n||c.y<1||c.y>m) continue;            
37             int k=mp[c.x][c.y];        
38             while(k)            
39             {
40                 c.x+=dx[i]*k;
41                 c.y+=dy[i]*k;
42                 if(c.x<1) c.x=1;if(c.x>n) c.x=n;
43                 if(c.y<1) c.y=1;if(c.y>m) c.y=m;
44                 k=mp[c.x][c.y];            
45             }
46             if(vis[c.x][c.y]) continue;            
47             if(c.x==ex&&c.y==ey)             
48             {
49                 printf("%d",c.step);
50                 return;
51             }
52             vis[c.x][c.y]=1;
53             q.push(c);
54         }    
55     }
56     printf("Impossible");
57 }
58 int main()
59 {//  freopen("input.txt","r",stdin);
60     n=read(),m=read(),k=read();    
61     for(int i=1;i<=k;i++)    
62     mp[read()][read()]=read(); 
63     sx=read(),sy=read();
64     ex=read(),ey=read();
65     bfs();    
66     return 0;
67 }
100昏

 T3 不老的传说

  • 题目描述(Description):

  一位先知告诉Ddynamic,在遥远的地方,有一处不老的泉水,在那里,他可以找到他人生的意义。按照先知的指引,Dynamic出发了。翻越雪山,穿过丛林,度过汪洋,终于来到了沙漠的深处。按照先知的说法,泉水就在这个地方。然而除了无尽的沙漠之外,什么都没有。

Dynamic几乎绝望了,他盲目地走着,突然来到了一圈奇异的巨石前,在巨石阵的中央清晰地传来泉水轻快的声音。巨大的石头挡住了去路,Dynamic无法前进了。突然间,本来无色的石头闪烁出绚丽夺目的光芒,与泉水声交织成诗一般的乐章。然后一刹那间,色彩消失了。

“这里面一定又什么秘密,我要把石头染成刚才的颜色!”Dynamic对自己说,他还清楚地记得每一块石头的颜色。智慧女神雅典娜这时出现了,递给他一把神奇的刷子,说“这把刷子每次可以把连续的不超过K块石头刷成一种新颜色,新刷的颜色会覆盖原来的颜色。用最少的次数,恢复石阵的光彩,你就会找到不老的泉水。”

Dynamic意识到这并不是一件容易的事,他出发得太匆忙,忘了带上手提电脑。你能帮助他吗?

  • 输入文件(dist.in):

  第1行包含3个整数N,C,K。其中N是石头的个数,C是颜色的种类,K是每次最多刷过的石头的个数。1≤N≤200,1≤C,K≤N 。

  第2行包含N个整数,分别是N块石头最终的颜色,按照顺时针的顺序。颜色是1到C之间的一个整数,整数之间用一个空格隔开。开始的时候,所有的石头都是无色的。

  • 输出文件(dist.out):

  输出一个整数,为需要的最少次数。

  • 样例(Sample):

Sample Input Case 1:

5 2 3

1 2 1 2 1

Sample Output Case 1:

3

好吧和参考程序长得差不多 是我太菜了,人大佬都学过,就我一脸蒙蔽 是我不配

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=200+10;
 4 const int inf=0x3f3f3f3f;
 5 int n,c,k,co[N<<1],dp[N<<1][N<<1],ans=inf;
 6 int rd()
 7 {
 8     int x=0,w=0;char ch=0;
 9     while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
10     while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
11     return w?-x:x;
12 }
13 
14 int dfs(int a,int b)
15 {
16     if(dp[a][b]!=inf) return dp[a][b];//此区间已经
17     if(a==b) return dp[a][b]=1;
18     if(a+k-1>=b&&co[a]==co[b]) return dp[a][b]=dfs(a,b-1);
19     if(a+k-1>=b&&co[a]!=co[b])
20         for(int i=a;i<=b-1;i++)
21         if(co[a]==co[i]) 
22         dp[a][b]=min(dp[a][b],dfs(a,i)+dfs(i+1,b));
23     if(a+k-1<b)//如果刷子的最大值无法覆盖到b 
24     for(int i=a;i<=a+k-1;i++)
25     if(co[a]==co[i])
26     dp[a][b]=min(dp[a][b],dfs(a,i)+dfs(i+1,b));
27     return dp[a][b];
28 }
29 
30 int main()
31 {
32     memset(dp,inf,sizeof(dp));
33     n=rd(),c=rd(),k=rd();
34     for(int i=1;i<=n;i++)
35     {co[i]=rd();co[i+n]=co[i];}//环形所以*2 
36     for(int i=1;i<=n;i++)//枚举从每个点开始涂色的最优方案 
37     ans=min(ans,dfs(i,i+n-1));
38     printf("%d",ans);
39     return 0; 
40 }
100昏
另一种方法,我还没mian懂那个一个石头一种颜色是什么操作
 1 int main()
 2 {
 3     int i,j,k,t;
 4     int c,K;
 5     while(scanf("%d%d%d",&n,&c,&K)!=EOF)
 6     {
 7         memset(dp,0,sizeof(dp));
 8         for(i=1; i<=n; i++)
 9         {scanf("%d",&a[i]);a[i+n]=a[i];}
10         for(i=1; i<=n<<1; i++)
11         for(j=i; j<=n<<1; j++)
12         dp[i][j]=j-i+1;  //起初设一块石头一种颜色
13         for(i=(n<<1)-1; i>0; i--)//dp预处理出从每个点开始涂色的最优方案
14         for(j=i+1; j<=2*n; j++)
15         {
16             dp[i][j]=dp[i+1][j]+1;//位置i要涂色,先把它预置好,再去求是否是最优的
17                 for(k=i+1; k<=j; k++)
18                 {
19                     if(a[i]==a[k]&&k-i+1<=K)//i,k最终颜色相同,如果i-k区间在给定一次刷的最大区间内,那么我们就可以一次刷好
20                      dp[i][j]=min(dp[i][j],dp[i+1][k]+dp[k+1][j]);
21                 }
22         int ans=INF;
23         for(i=1;i<=n;i++)//枚举起点找dp最小值
24         ans=min(ans,dp[i][i+n-1]);
25         printf("%d\n",ans);
26     }
27     return 0;
28 }  
100昏

 

总结

  • 不要总想着骚操作,平平淡淡才是真!得分才是最重要的
  • 不要死在一种方法上了,如果一种方法想不出来,就试试其他jio度,或者骗分
  • 大佬永远是大佬,蒟蒻是比不过的,踏踏实实骗分

转载于:https://www.cnblogs.com/lxyyyy/p/10317259.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值