关闭

ADS-WK11-Review of Programming Contest Rules-回溯剪枝

标签: pta
1017人阅读 评论(0) 收藏 举报
分类:

【题目】

The ACM ICPC's rule of scoring is as the following:

A problem is solved when it is accepted by the judges. Teams are ranked according to the most problems solved. For the purposes of awards, or in determining qualifier(s) for the World Finals, teams who solve the same number of problems are ranked by least total time. The total time is the sum of the time consumed for each problem solved. The time consumed for a solved problem is the time elapsed from the beginning of the contest to the submittal of the accepted run plus 20 penalty minutes for every rejected run for that problem regardless of submittal time. There is no time consumed for a problem that is not solved.

For example, if one has the following contest record:

  • At the 100th minute submitted problem A, rejected;
  • At the 140th minute submitted problem B, rejected;
  • At the 150th minute submitted problem B, accepted;
  • At the 160th minute submitted problem C, accepted.

Then his total time = (150+20) + 160 = 330. Notice that it took him only 10 minutes to finish problem C. Assume that he spent 40 minutes on reading all the problems through, then if he could do problem C first and problem A last, his contest record might look like:

  • At the 50th minute submitted problem C, accepted;
  • At the 90th minute submitted problem B, rejected;
  • At the 100th minute submitted problem B, accepted;
  • At the 160th minute submitted problem A, rejected.

Then his total time would be 50 + (100+20) = 170. Hence the order of solving the problems will affect one's final rank.

Now suppose that you are in a one-person team. It will take you t0t0minutes to read all the problems through. Judging by your experience, you may estimate the minutes titi that you will take to solve problem ii. And more, the earlier you get one problem done, the more unlikely that you will make mistakes on programming. Assume that if a solution is first time submitted in the first hour (60 minutes inclusive), it will get accepted at once; if it is first time submitted in the second hour, it will be rejected once; if it is first time submitted in the third hour, it will be rejected twice; etc. You may also estimate the minutes didi for debugging problem ii every time it is rejected. For the sake of simplicity, let us assume that didi is fixed for each problem ii, and once you start working on a problem, you will keep submitting until it is accepted.

Your task is to write a program to find yourself the order of solving the problems which gives you the best chance of winning the contest.

Input Specification:

Each input file contains several test cases. For each test case, the 1st line contains 3 integers: the total number of contest hours H (0 < H  5), the total number of problems N (0 < N  9), and the time t0t0 (minutes) for you to read through all the problems at the beginning of the contest. The following N lines each contains a problem's name and a pair of positive integers titi and didi. A problem's name is a string of no more than 20 characters without any space. A negative H signals the end of input.

Output Specification:

For each test case, you are supposed to print to standard output the total time in a line in the format shown by the sample. Then print the names of the problems you will solve in the correct order, each name in a line. If there are several solutions, you must output the smallest sequence. A sequence of problems { i1i1i2i2, ... inin } is smaller than another sequence { j1j1j2j2, ... jnjn } means that there exists an integer KK between 1 and nn such that for every 1kK1k<K, we have ikjkik=jk, and iKjKiK<jK.


【代码】

#include <iostream>
#include <string.h>
#define MAXP 10
using namespace std;

int H=0,N,T0;
int T[MAXP],D[MAXP];//T:题目完成时间 D:题目debug时间
string problem_name[MAXP];
int fin_pro_No[MAXP];//按顺序记录完成的题目序号
bool pro_state[MAXP];//记录题目完成情况:true该题完成 false该题未完成
int final_num;
int final_pro_No[MAXP];
int final_totalTime;

void update_strategy(int num, int totalTime){
    //控制策略的选择
    if (num < final_num) return;//优先选择做出题数多的策略
    if (num == final_num && totalTime>=final_totalTime) return;//做出题数一样,选择时间少的
    //更新策略
    final_num = num;
    final_totalTime = totalTime;
    for (int i=0; i<num; i++) {
        final_pro_No[i]=fin_pro_No[i];
    }
}

//num:完成的题数
//usedTime:用掉的时间
//totalTime:成绩时间
void dfs(int num, int usedTime, int totalTime){
    
    int first_submit_time = usedTime + T[fin_pro_No[num]];
    int debug_times = (first_submit_time - 1)/60;
    int next_usedTime = first_submit_time + debug_times * D[fin_pro_No[num]];
    int next_totalTime = totalTime + next_usedTime + debug_times*20;
    
    if (next_usedTime <= H*60) {//规定时间内能成功提交本题
        num ++;
        if (num < N) {//还有未完成的题
            for (int i =0; i<N; i++) {//尝试每个可走的岔路
                if (!pro_state[i]) {
                    pro_state[i]=true;
                    fin_pro_No[num]=i;
                    dfs(num, next_usedTime, next_totalTime);
                    pro_state[i]=false;//===>剪枝
                    //不用num--,num是形参,每层的num都不一样
                }
            }
        }
        else update_strategy(num, next_totalTime);//无题可做。找到一种策略,回到上一层===>
    }
    else update_strategy(num, totalTime);//超时。找到一种策略,回到上一层===>
}

int main(){
    cin >> H;
    while (H>0) {
        cin >> N >> T0;
        for (int i=0; i<N; i++) {
            cin >> problem_name[i] >> T[i] >> D[i];
        }
        //变量初始化
        final_num = 0;
        final_totalTime = ~(1 << 31);
        memset(final_pro_No,0,sizeof(final_pro_No));
        memset(fin_pro_No, 0, sizeof(fin_pro_No));
        memset(pro_state, false, sizeof(pro_state));
        
        for (int i=0; i<N; i++) {
            pro_state[i]=true;
            fin_pro_No[0]=i;
            dfs(0, T0, 0);//用掉的时间为读题时间,成绩时间为0
            pro_state[i]=false;
        }
        
        cout << "Total Time = " << final_totalTime << endl;
        for (int i=0; i<final_num; i++) {
            cout << problem_name[final_pro_No[i]] << endl;
        }
        
        cin >> H;
    }
    
    return 0;
}

参考:http://blog.csdn.net/zccz14/article/details/51449748


0
0
查看评论

PTA Review of Programming Contest Rules

按照ACM/ICPC的比赛计分规则(解题数+20分钟罚时规则),给定比赛时间、总题数。 假设某个人是这样做题的: 1. 用一定时间通读所有的题,计算出解出每个题目所需的时间,以及如果错了,调试一次所需的时间。 2. 他一旦开始做某题,不做出来就不换题(一不做二不休)。 3. 对于每道题,他第一次提...
  • zccz14
  • zccz14
  • 2016-05-19 02:06
  • 1676

ads 下 malloc堆分配问题

昨天晚上碰到个ads下c库的malloc内存分配的问题。程序一跑到malloc和memset就异常中断,一直都不知道原因。 今天查了些资料,稍微对ads下无os支持下的malloc有了初步的认识。 一:堆的基地址由于malloc是需要在堆空间上进行内存分配的,因此需要知道堆空间的基地址,而...
  • hl1985
  • hl1985
  • 2009-09-25 15:23
  • 2195

ADS调试程序时进入死循环

[现象]在用ARM的ADS调试的时候,在调试某一行看起来极其简单,应该不会出错的程序时候,按F8希望进入该函数,但是整个程序却死了,中断运行,显示的信息如下所示:DBE Warning 00056: The statement into which was stepped is singular (...
  • armeasy
  • armeasy
  • 2010-04-25 22:36
  • 1508

为什么int型的数组用memset不能清零(memset的使用规范)

问题:为什么这样用memset不能清零 #include #include int main() {    int i,a[100];    memset(a,0,100);//改memset(a,0,sizeof(a));或m...
  • Stephen_yu
  • Stephen_yu
  • 2015-05-21 14:16
  • 6120

关于回溯剪枝算法的讨论

作为通用解题法的回溯,虽然在方法本质上毫无高妙之处,却是解决许多NP时间复杂性问题的唯一选择。这个假期笔者接触了一些比较有代表意义的回溯题目,从一些犯下的错误中获得了一些感受,下面谈一谈我的一点粗浅的体会。 一、谨慎地辨别是不是仅用贪心算法而不用回溯就可以解决问题 大家知道,
  • metasearch
  • metasearch
  • 2011-09-30 14:45
  • 630

回溯法加剪枝解决01背包问题(C++)

01 背包问题: knapsack 是解决如何将一个背包的价值最大划的问题  输入:  c 背包最大容量,w[] 物品的重量 ,v[] 物品的价值  输出:bestv 最大的可放置在背包内的物品价值总和,bestX[] 对应bestp的物品取法,即最优值和最优解 ...
  • weixin_40184101
  • weixin_40184101
  • 2018-01-04 14:28
  • 74

2015-2016 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2015) Goblin Garden Guards (数论)

题目大意:在第一象限内存在着n个黑点,然后同时存在着圆,求出不在圆内的个数 解题思路:本来这道题在数据很小的时候可以暴力去判,但是发现这个数据太大,所以需要进行优化和处理,我们枚举每个圆,找出这个圆作为内切圆的正方形,然后枚举在正方形内是否有黑点且黑点在圆内 #include #include...
  • qq_34826781
  • qq_34826781
  • 2017-08-02 17:03
  • 249

2015 Pacific Northwest Region Programming Contest—Division 2 Problem P — Complexity(字符串、贪心)

题意:给你一个字符串,定义复杂度为字符的种类。问你最少删除几个字符,能使种类最多为两种? 题目还行,注意一点,aabbbcccc这种情况,不要光判断种类数。 代码如下,用了一点简单的hash。 #include using namespace std; int main() { cha...
  • Cutec_lbq
  • Cutec_lbq
  • 2017-08-12 14:29
  • 263

数独:深搜+剪枝 == 递归+回溯

题目描述 数独是一个我们都非常熟悉的经典游戏,运用计算机我们可以很快地解开数独难题,现在有一些简单的数独题目,请编写一个程序求解。 输入描述: 输入9行,每行为空格隔开的9个数字,为0的地方就是需要填充的。 输出描述: 输出九行,每行九个空格隔开的数字,为解出的答案...
  • qq_29108585
  • qq_29108585
  • 2017-04-09 13:25
  • 361

回溯经典剪枝——小木棍

经典回溯题——小木棍
  • cjj122
  • cjj122
  • 2017-07-25 16:01
  • 232
    个人资料
    • 访问:3710次
    • 积分:77
    • 等级:
    • 排名:千里之外
    • 原创:4篇
    • 转载:0篇
    • 译文:0篇
    • 评论:1条
    文章分类
    最新评论