1269: 爱看电视的LsF+遥控器 dfs+剪枝
2017-04-24 22:00
162 查看
1269: 爱看电视的LsF
时间限制: 1 秒 内存限制: 64 MB提交: 292 解决: 70
提交 状态
题目描述
LsF(刘师傅)非常喜欢看电视!不幸的是,遥控器上的一些数字按钮坏了。 但他灵光一闪,如果他不能直接输入他想要看到的频道的号码,那么他可以先输入其他号码,再通过按下按钮+ 和- (这两个按钮由24K钛合金制成,永远不会坏)的方式到达所需的频道。 按钮+将数字增加1,按钮-将数字减少1。当然他依然可以使用那些完好无损的数字按钮输入号码。
他最初在第S频道,他想看第T频道。他想知道由S到T频道所需的最少按钮按压次数。
输入
输入包含多组数据。对于每组数据,第一行是三个整数n,S,T(n≤10,0≤S,T≤500,000。 第二行是n个数字 a1,a2,...,an,表示数字 ai键已经坏了 (0≤ai≤9,ai≠aj when i≠j)。
输出
输入包含多组数据。对于每组数据,第一行是三个整数n,S,T(n≤10,0≤S,T≤500,000。 第二行是n个数字 a1,a2,...,an,表示数字 ai键已经坏了 (0≤ai≤9,ai≠aj when i≠j)。
样例输入
10 1 100
0 1 2 3 4 5 6 7 8
9
9 1 100
0 1 2 3 4 5 6 7 8
样例输出
99
3
代码:用了深搜,最后发现这样做给自己挖了很多坑,但是缝缝补补的还是过了。。。思路是深搜尽可能接近要搜的频道。。
#include<stdio.h> #include<string.h> #include<algorithm> #include<math.h> using namespace std; int vis[15]; int ans[500000]; int n,S,T; int res; void dfs(int sum,int count) { // printf("********************\n"); // for(int i=0;i<count;i++) printf("%d",ans[i]); // printf("sum==%d count==%d res==%d\n",sum,count,res); if(count>res) return ;//超过当前最优,返回 if(sum==0&&count>10) return ; if(sum==T)//到达T,与当前最少按键次数比较 { // for(int i=0;i<count;i++) printf("%d",ans[i]); // printf("sum==%d count==%d res==%d ==\n",sum,count,res); res=min(res,count); // printf("sum==%d count==%d res==%d ==\n",sum,count,res); return ; } if(sum>T)//超了以后按减 { // for(int i=0;i<count;i++) printf("%d",ans[i]); // printf("\tsum==%d count==%d res==%d >>%d\n",sum,count,res,count+sum-T); dfs(T,count+sum-T); return ; } for(int i=0;i<=9;i++)//按数字 { if(vis[i]) continue; ans[count]=i; if(count+1<res) dfs(sum*10+i,count+1); } if(count!=0) ans[count]=-1,dfs(T,count+T-sum);//按加 ,在当前所搜的台的基础上,sum=0的时候需要特判 } int main() { while(~scanf("%d%d%d",&n,&S,&T)) { memset(vis,false,sizeof(vis)); for(int i=0;i<n;i++) { int a; scanf("%d",&a); vis[a]=true; } // if(S==0&&T==500000) // { // printf("1\n"); // continue; // } if(S==T) { printf("0\n"); continue ; } int temp=S; for(int i=0;i<10;i++) { if(!vis[i]&&i<temp) temp=i; } if(T==0)//特判,否则T==0影响dfs()结束条件 { //if(!vis[0]) printf("1\n"); if(temp==S) printf("%d\n",temp); else printf("%d\n",temp+1); continue ; } res=5000000; dfs(0,0); res=min(res,(int)fabs(T-S)); printf("%d\n",res); } }
1617 : 遥 控 器
时间限制:1 Sec 内存限制:128 MiB提交:43 答案正确:15提交 状态 讨论区
题目描述
Dr.Kong 有一台高级电视机,这台电视机可以接受100个频道(从0到99编号)。电视的配套遥控器有13个按钮:1 2 3 ↑
4 5 6 ↓
7 8 9
— 0
当按"↑"键时,当前频道编号会增加1(如果当前为99频道,则会切换到0频道)。如果按"↓"键,当前频道编号会减小1(如果当前为0频道,则会切换到99频道)。当要切换到0~9频道时,可以直接在遥控器上按相应的键。当要切换到10~99频道时,可以先按"—"键,然后按2个与频道编号相对应的数字键(即先按与频道编号的十位数字相对应的键,然后按与个位数字相对应的键)。
由于遥控器长时间的使用和某些未知原因,遥控器上的某些键已经坏了,不能再起作用了。现在你的任务是,能否告诉Dr.Kong,如何用最少的按键次数来将频道从编号X切换到编号Y。
输入
第一行: N 表示有N组测试数据。 (1<=N<=5)对每组测试数据有5行,前4行包含遥控器上每个按键的信息。0表示对应的键坏了,1表示对应的键可以使用。第5行包含2个整数,分别是X 和 Y (0 <= X <= 99; 0 <= Y <= 99)。
输出
对每组测试数据输出一行,即将频道从编号X切换到编号Y所需要的最小按键次数。如果不可能将频道从编号X 切换到编号Y,则输出-1.样例输入
复制2 0 0 1 1 1 1 1 1 1 1 1 1 1 23 52 1 1 1 0 1 1 1 0 1 0 1 0 1 23 52
样例输出
复制4 -1代码:广搜,是所搜的频道尽可能逼近目标频道。。
#include<stdio.h>/*
#include<string.h>
#include<algorithm>
#include<queue>
#include<math.h>
using namespace std;
int n,S,T;
bool vis[15];
// 0 1 2 3-------1 2 3 +
// 4 5 6 7-------4 5 6 -
// 89 10 -------89 10
// 11 12 ------ —0
bool sub,add,as;
int res;
int maxx;
struct Node
{
int sum;
int count;
Node(){}
Node(int _sum,int _count)
{
sum=_sum;
count=_count;
}
};
void bfs()
{
queue<Node> q;
Node node;
node.sum=0;
node.count=0;
q.push(node);
maxx=0;
while(!q.empty())
{ if(q.size()>maxx) maxx=q.size();
node =q.front();
q.pop();
int sum=node.sum;
int count=node.count;
// printf("q.size==%d sum==%d count===%d res==%d\n",q.size(),sum,count,res);
if(count>res) continue;//最多按一百次
if(sum==T)
{
res=min(res,count);
continue;
}
if(sum>T)
{
if(sub) res=min(res,sum-T+count);//按减
continue;
}
if(count!=0&&add) res=min(res,T-sum+count);//q.push(Node(T,T-sum+count));//按加
if(count==0)
{
for(int i=0;i<=9;i++)//按按键
{
if(!vis[i]) continue ;
if(count+1<res) q.push(Node(sum*10+i,count+1));
}
}
else if(count>0&&as)
{
if(count==1) count++;//printf("Yes\n"),;//第二次按,加上—
for(int i=0;i<=9;i++)//按按键
{
if(!vis[i]) continue ;
if(count+1<res) q.push(Node(sum*10+i,count+1));
}
}
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(vis,false,sizeof(vis));
for(int i=0;i<13;i++)
{
int a;
scanf("%d",&a);
switch(i)
{
case 0: vis[1]=a;break;
case 1: vis[2]=a;break;
case 2: vis[3]=a;break;
case 3: add=(a==1);break;
case 4: vis[4]=a;break;
case 5: vis[5]=a;break;
case 6: vis[6]=a;break;
case 7: sub=(a==1);break;
case 8: vis[7]=a;break;
case9: vis[8]=a;break;
case 10: vis[9]=a;break;
case 11: as=(a==1);break;
case 12: vis[0]=a;break;
}
}
scanf("%d%d",&S,&T);
// if(sub&&as&&add) printf("0\n");
// for(int i=0;i<10;i++) if(vis[i]) printf("%d ",i);
res=101;
if(T==99&&S==0&&sub)
{
printf("1\n");
continue ;
}
if(T==0&&S==99&&add)
{
printf("1\n");
continue ;
}
//因为台是可循环的,一定要判断两个台之间的相对距离
if(add&&T>S)res=min(res,(int)fabs(T-S));
if(sub&&T>S)res=min(res,(int)fabs(S+99-T+1));
if(sub&&T<S)res=min(res,(int)fabs(T-S));
if(add&&T<S)res=min(res,(int)fabs(T+99-S+1));
bfs();
// printf("max==%d\n",maxx);
if(res==101)printf("-1\n");
else printf("%d\n",res);
}
}
100
1 1 1 1
1 1 1 1
1 1 1
1 1
099
0 0 0 1
0 0 0 1
0 0 0
0 0
75 5
0 0 0 1
0 0 0 1
0 0 0
0 0
5 75
0 0 1 1
1 1 1 1
1 1 1
1 1
23 52
1 1 1 0
1 1 1 0
1 0 1
0 1
23 52
*/
相关文章推荐
- haut 1269: 爱看电视的LsF dfs
- HAUTOJ 玲珑杯 1269: 爱看电视的LsF(暴力)
- HAUTOJ 1269 爱看电视的LsF
- 【hautoj 1269: 爱看电视的LsF】+ 暴力
- 刚刚看电视听到的几句话(虽不是至理名言,但可引人深思)
- bnu1269 报数游戏 C语言版
- POJ 1269
- POJ 1269
- POJ 1269 Intersecting Lines
- poj 3373 Changing Digits (DFS+剪枝)
- POJ 1269 Intersecting Lines 判断直线关系(相交(求交点),重合,平行)
- hdu 1269 迷宫城堡
- poj 2362 || zoj 1909 Square (DFS+剪枝)
- [HDU] 1269 迷宫城堡-最简单的强连通分支题
- HDU1269 迷宫城堡(有向图的强连通分量(scc))
- POJ 1269 Intersecting Lines(直线相交判断,求交点)
- 看电视(今年暑假不AC)
- poj 1269 水题
- HDU 1269 迷宫城堡
- POJ 1269 Intersecting Lines