zoukankan      html  css  js  c++  java
  • Sicily 1176. Two Ends 解题报告

    1176_Two_Ends

    题目链接:

    http://soj.me/1176

    题目大意:

    很简单的一道题目,甲乙从卡片堆中轮流拿卡片,要使甲得到的卡片数字和最大,求这时甲乙数字和的差.两个人每次只能拿卡片队列中最左边或者最右边的一张,而乙每次已经设定好都会拿左右两张中比较大那张(相同的话拿左边的).说白就是求一个使甲能拿到最大数字和的策略

    思路:

    假设卡片序号为0到n - 1,(a,b)表示从序号a到b的卡片中甲能拿到的最大和,要求的(a,b),需要首先求出(a,b - 2),(a + 1, b - 1)和(a + 2, b),在这三种情况中甲乙各再取一张卡片,哪种使得甲的和最大的话结果就是哪个.一开始使用递归的方法超时了,因为整个过程中确实进行了很多重复的计算,所以增加了数组record[][]来记录产生的过程结果,避免重复计算,其实就是动态规划中带记录的自顶向下的方法.

    代码:

    #include <iostream>
    #include <memory.h>
    using namespace std;
    
    
    int record[1001][1001];//用来记录递归过程产生的结果,避免重复的计算节省时间
    
    int get_best_points_recursive(int *cards, int left_index, int right_index);
    
    int main() {
    	int n, count = 1;
    	while (cin >> n && n != 0) {
    		memset(record, 0, sizeof(record));
    		int cards[n], total_points = 0;
    		for (int i = 0; i < n; ++i) {
    			cin >> cards[i];
    			total_points += cards[i];
    		}
    
    		int best_points = get_best_points_recursive(cards, 0, n - 1);
    
    		cout << "In game " << count
    				<< ", the greedy strategy might lose by as many as "
    				<< best_points - (total_points - best_points) << " points."
    				<< endl;
    		count++;
    	}
    	return 0;
    }
    
    int get_best_points_recursive(int *cards, int left_index, int right_index) {
    	if (record[left_index][right_index] == 0) {//这个区间的结果没计算过需要计算并将结果存到record中
    		if (right_index - left_index == 1) {
    			record[left_index][right_index] = max(cards[left_index],
    					cards[right_index]);
    		} else {
    			int left_max, right_max; //先取左边一张的最大和和先取右边一张的最大和
    			if (cards[left_index + 1] >= cards[right_index]) { //对手在剩下的卡片中拿左边的那张
    				left_max = cards[left_index]
    						+ get_best_points_recursive(cards, left_index + 2,
    								right_index);
    			} else {
    				left_max = cards[left_index]
    						+ get_best_points_recursive(cards, left_index + 1,
    								right_index - 1);
    			}
    			if (cards[left_index] >= cards[right_index - 1])
    				right_max = cards[right_index]
    						+ get_best_points_recursive(cards, left_index + 1,
    								right_index - 1);
    			else
    				right_max = cards[right_index]
    						+ get_best_points_recursive(cards, left_index,
    								right_index - 2);
    			record[left_index][right_index] = max(left_max, right_max);
    		}
    	}
    	return record[left_index][right_index];
    }
    
  • 相关阅读:
    流浪西邮之寻找火石碎片
    给你一个666
    似魔鬼的步伐
    括号匹配2019
    挑剔程度
    到底有到少个小和尚?
    获取任务栏所有正在运行程序
    EXTJS4创建多级菜单
    关于时间的一些理解
    kof97调隐藏人物
  • 原文地址:https://www.cnblogs.com/jolin123/p/3975231.html
Copyright © 2011-2022 走看看