zoukankan      html  css  js  c++  java
  • 第九届蓝桥杯B组决赛-调手表

    标题:调手表


    小明买了块高端大气上档次的电子手表,他正准备调时间呢。
    在 M78 星云,时间的计量单位和地球上不同,M78 星云的一个小时有 n 分钟。
    大家都知道,手表只有一个按钮可以把当前的数加一。在调分钟的时候,如果当前显示的数是 0 ,那么按一下按钮就会变成 1,再按一次变成 2 。如果当前的数是 n - 1,按一次后会变成 0 。
    作为强迫症患者,小明一定要把手表的时间调对。如果手表上的时间比当前时间多1,则要按 n - 1 次加一按钮才能调回正确时间。
    小明想,如果手表可以再添加一个按钮,表示把当前的数加 k 该多好啊……
    他想知道,如果有了这个 +k 按钮,按照最优策略按键,从任意一个分钟数调到另外任意一个分钟数最多要按多少次。
    注意,按 +k 按钮时,如果加k后数字超过n-1,则会对n取模。
    比如,n=10, k=6 的时候,假设当前时间是0,连按2次 +k 按钮,则调为2。


    「输入格式」
    一行两个整数 n, k ,意义如题。


    「输出格式」
    一行一个整数
    表示:按照最优策略按键,从一个时间调到另一个时间最多要按多少次。


    「样例输入」
    5 3


    「样例输出」
    2


    「样例解释」
    如果时间正确则按0次。否则要按的次数和操作系列之间的关系如下:
    1:+1
    2:+1, +1
    3:+3
    4:+3, +1


    「数据范围」
    对于 30% 的数据 0 < k < n <= 5
    对于 60% 的数据 0 < k < n <= 100
    对于 100% 的数据 0 < k < n <= 100000


    资源约定:
    峰值内存消耗(含虚拟机) < 256M
    CPU消耗  < 1000ms
    思路:广搜||DP

    代码:

     1 /*///由于每个时间最多可以通过+1/+k变成两种时间,而每个时间如果已经在前面得出,则就是最少步数了
     2 #include<bits/stdc++.h>
     3 using namespace std;
     4 const int maxn=1e5+5;
     5 struct node{
     6     int cnt,time;
     7 }n1,n2;
     8 int num[maxn];
     9 bool vis[maxn];
    10 void bfs(int n,int k){
    11     queue<node>Q;
    12     Q.push({0,0});
    13     vis[0]=true;
    14     while(!Q.empty()){
    15         n1=Q.front();
    16         Q.pop();
    17         int nex=(n1.time+1)%n;
    18         if(!vis[nex]){
    19             vis[nex]=true;
    20             n2.cnt=n1.cnt+1;
    21             n2.time=nex;
    22             num[nex]=n2.cnt;
    23             Q.push(n2);
    24         }
    25         nex=(n1.time+k)%n;
    26         if(!vis[nex]){
    27             vis[nex]=true;
    28             n2.cnt=n1.cnt+1;
    29             n2.time=nex;
    30             num[nex]=n2.cnt;
    31             Q.push(n2);
    32         }
    33     }
    34 }
    35 int main(){
    36     int n,k;
    37     scanf("%d%d",&n,&k);
    38     bfs(n,k);
    39     int Max=-1;
    40     for(int i=0;i<n;i++){
    41         Max=max(Max,num[i]);
    42     }
    43     printf("%d
    ",Max);
    44     return 0;
    45 }
    46 */
    47 #include<bits/stdc++.h>
    48 using namespace std;
    49 int dp[100005];
    50 int main(){
    51     int n, k;
    52     cin>>n>>k;
    53     ///下面两个初始化不可少,因为那是dp的初始状态
    54     for(int i = 0; i < n; i++) dp[i] = i; // 初始化为多少分钟就要调多少次,默认一次调一分钟
    55     for(int i = k; i < n; i += k) //从0出发,每+k步数就加一次
    56         dp[i] = dp[i - k] + 1;
    57     int sum = -1;
    58     while(1){ // 如果结果收敛,则停止循环,这里我们算他们的和,如果他们的步数和不变了,说明收敛了
    59         int now_sum = 0;
    60         for(int i = 1; i < n; i++){
    61             now_sum += dp[i];
    62             dp[i] = min(dp[(i + n - k) % n] + 1, dp[i - 1] + 1);// 每一步都可以由上一步调k步或者1步得到
    63         }
    64         if(now_sum == sum) break;
    65         sum = now_sum;
    66     }
    67     int maxdp = dp[0];
    68     for(int i = 0; i < n; i++){
    69 //        cout<<dp[i]<<" ";
    70         maxdp = max(dp[i], maxdp);
    71     }
    72     cout<<maxdp<<endl;
    73     return 0;
    74 }
    View Code
  • 相关阅读:
    URAL 2067 Friends and Berries (推理,数学)
    URAL 2070 Interesting Numbers (找规律)
    URAL 2073 Log Files (模拟)
    URAL 2069 Hard Rock (最短路)
    URAL 2068 Game of Nuts (博弈)
    URAL 2066 Simple Expression (水题,暴力)
    URAL 2065 Different Sums (找规律)
    UVa 1640 The Counting Problem (数学,区间计数)
    UVa 1630 Folding (区间DP)
    UVa 1629 Cake slicing (记忆化搜索)
  • 原文地址:https://www.cnblogs.com/liuzuolin/p/10896672.html
Copyright © 2011-2022 走看看