• POJ 1243 One Person


    题意:

    猜数字, 给定 G, L, G 表示可以猜的次数, 每猜一次, G减一, 假如猜的 number 大于 target, L 还需减一, 当 L == -1 或者 G==0 时, 若还没猜中, 则失败

    思路:

    1. 举例子

      <1> 当 G = 3, L = 0 时, 只能从 1 向上猜, 最大的数字是 3

      <2> 当 G = 2, L = 1 时, 不必从 1 猜起, 假设猜 k, 假如小了, 状态变成 <G,L>(1,0), 由 (1) 得到的规律知, k 不能大于 2; 假如大了, 那么状态变成 <G,L>(1,1), 还有一次机会, 可见, <G,L>(2,1) 等于 3

      <3> 当 <G,L>(3,1) 时, 仍然假设猜 K, 假如小了, 状态变成 <G,L>(2,0), 假如大了, 变成<G,L>(2,1), 又 <G,L>(2,1)可以保证3个数能被猜出, 所以 <3,1> 等于 6

    2. 从 1 的例子足以看出规律, 一个状态<G,L> 能够保证多少个数能被猜出, 比如 <G,L>(3,1)=6,  <G,L>(3,0)=3, <G,L>(2,1)=3

    3. 状态转移方程, dp[i][j] 表示G=i, L = j 在最差的情况下能够保证被猜出数的个数

      dp[i][j] = dp[i-1][j-1] (low 了) + 1 + dp[i-1][j](high)了 

    4. 如果 j >= i, 那么 dp[i][j] = dp[i][i-1]

    总结:

    1. 第 11 行代码, j 应该从 1 开始, WA 过一次

    代码:

    #include <iostream>
    using namespace std;
    
    int G, L;
    int dp[100][100];
    int solve_dp() {
    	for(int i = 0; i <= G; i++)
    		dp[i][0] = i;
    
    	for(int i = 1; i <= G; i ++) {
    		for(int j = 1; j <= L; j++) {
    			if(j >= i)
    				dp[i][j] = dp[i][i-1];
    			else
    				dp[i][j] = dp[i-1][j-1]+1+dp[i-1][j];
    		}
    	}
    	return dp[G][L];
    }
    
    int main() {
    	freopen("E:\Copy\ACM\测试用例\in.txt", "r", stdin);
    	int testcase = 0;
    	while(scanf("%d%d", &G, &L) && G != 0) {
    		testcase++;
    		printf("Case %d: %d
    ", testcase, solve_dp());
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    python2.7学习记录之三
    编程题
    解题的小问题(C++)
    算法入门(C++)
    逻辑回归
    入门级(python)
    python2.7学习记录之二
    sql语句-排序后加入序号再运算判断取想要的项
    linux中c多线程同步方法
    进程间的通讯方式
  • 原文地址:https://www.cnblogs.com/xinsheng/p/3463092.html
Copyright © 2020-2023  润新知