博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[Offer收割]编程练习赛3 - 题目3 : 智力竞赛
阅读量:7025 次
发布时间:2019-06-28

本文共 3329 字,大约阅读时间需要 11 分钟。

智力竞赛 

 ----------------------------------------------------------------------------

Mean: 

略(中文题).

analyse:

比赛中最先想到的是三维dp,但思考后发现可以压缩为二维,状态转移方程:

  • dp[i][j]=min(dp[i][j],dp[i][j-(right+fault)]+right)

其中dp[i][j]表示:

  • 到通过第i关为止,在总共只有j次答题机会的情况下,总共至少需要答对dp[i][j]次

最终answer为dp[n][m].

Time complexity: O(N*M*M)

 

view code

/**
* -----------------------------------------------------------------
* Copyright (c) 2016 crazyacking.All rights reserved.
* -----------------------------------------------------------------
*       Author: crazyacking
*       Date  : 2016-03-30-21.00
*/
#include <queue>
#include <cstdio>
#include <set>
#include <string>
#include <stack>
#include <cmath>
#include <climits>
#include <map>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using
namespace
std;
typedef
long
long(
LL);
typedef
unsigned
long
long(
ULL);
const
double
eps(
1e-8);
const
int N
=
1010;
LL
a
[N
],
dp
[N
][N
];
int
main()
{
   
int
Cas;
   
cin
>>
Cas;
   
while(
Cas
--)
   
{
       
int n
,
m
,s
,
t;
       
cin
>>n
>>
m
>>s
>>
t;
       
for(
int
i
=
1;
i
<=n;
++
i)
       
{
           
cin
>>
a
[
i
];
           
fill(
dp
[
i
],
dp
[
i
]
+N
,
INT_MAX);
       
}
       
fill(
dp
[
0
],
dp
[
0
]
+N
,
0);
       
for(
int
i
=
1;
i
<=n;
++
i)
       
{
           
int
max_right
=
a
[
i
]
/s;
           
if(
a
[
i
]
%s)
++
max_right;
           
for(
int
right
=
0;
right
<=
max_right;
++
right)
           
{
               
int
dif
=
a
[
i
]
-s
*
right
,
fault
=
0;
               
if(
dif
>
0)
               
{
                   
if(
dif
%
t)
fault
=
dif
/
t
+
1;
                   
else
fault
=
dif
/
t;
               
}
               
fault
=
max(
fault
,
0);
               
for(
int
chance
=
m;
chance
>=
right
+
fault;
--
chance)
                   
dp
[
i
][
chance
]
=
min(
dp
[
i
][
chance
],
dp
[
i
-
1
][
chance
-(
right
+
fault
)]
+
right);
           
}
       
}
       
if(
dp
[n
][
m
]
<
INT_MAX)
           
cout
<<
dp
[n
][
m
]
<<
endl;
       
else
           
cout
<<
"No"
<<
endl;
   
}
   
return
0;
}
/*
*/
/**< 带注释版 */
/**
* -----------------------------------------------------------------
* Copyright (c) 2016 crazyacking.All rights reserved.
* -----------------------------------------------------------------
*       Author: crazyacking
*       Date  : 2016-03-30-21.00
*/
#include <queue>
#include <cstdio>
#include <set>
#include <string>
#include <stack>
#include <cmath>
#include <climits>
#include <map>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using
namespace
std;
typedef
long
long(
LL);
typedef
unsigned
long
long(
ULL);
const
double
eps(
1e-8);
const
int N
=
1010;
LL
a
[N
],
dp
[N
][N
];
int
main()
{
   
int
Cas;
   
cin
>>
Cas;
   
while(
Cas
--)
   
{
       
int n
,
m
,s
,
t;
       
cin
>>n
>>
m
>>s
>>
t;
       
for(
int
i
=
1;
i
<=n;
++
i)
       
{
           
cin
>>
a
[
i
];
           
fill(
dp
[
i
],
dp
[
i
]
+N
,
INT_MAX);
       
}
       
fill(
dp
[
0
],
dp
[
0
]
+N
,
0);
       
for(
int
i
=
1;
i
<=n;
++
i)
// 到第i关为止
       
{
           
//对于本关,答对max_right题时,不算错题的分值也能通关
           
int
max_right
=
a
[
i
]
/s;
           
if(
a
[
i
]
%s)
++
max_right;
           
for(
int
right
=
0;
right
<=
max_right;
++
right)  
// 枚举答对的题数
           
{
               
//答对right题时,需要答错多少题
               
int
dif
=
a
[
i
]
-s
*
right
,
fault
=
0;
               
if(
dif
>
0)
               
{
                   
if(
dif
%
t)
fault
=
dif
/
t
+
1;
                   
else
fault
=
dif
/
t;
               
}
               
fault
=
max(
fault
,
0);
               
for(
int
chance
=
m;
chance
>=
right
+
fault;
--
chance)
                   
dp
[
i
][
chance
]
=
min(
dp
[
i
][
chance
],
dp
[
i
-
1
][
chance
-(
right
+
fault
)]
+
right);
               
// dp[i][j] ------到本关为止,若只有chance次答题机会,本关答对了right题,若本关能够通关,到本关为止总共最少需要答对多少题
               
// chance-(right+fault) ----- 总共答题机会为chance,本关用了right+fault次,前面所有关只有chance-(right+fault)次机会
           
}
       
}
       
if(
dp
[n
][
m
]
<
INT_MAX)
           
cout
<<
dp
[n
][
m
]
<<
endl;
       
else
           
cout
<<
"No"
<<
endl;
   
}
   
return
0;
}
/*
*/

 

转载地址:http://osoxl.baihongyu.com/

你可能感兴趣的文章
tomcat启动是报Multiple Contexts have a path of "/XXX"
查看>>
AC-50207: Fatal: Failed to execute one or more of the config tools during Contex
查看>>
读书笔记《集体智慧编程》Chapter 3 : Discovering Groups
查看>>
python大数据工作流程
查看>>
MySQL数据库学习研究(细究Percona Server 5.6)
查看>>
XCode快捷键
查看>>
人脸识别&ORC的Demo
查看>>
数据库设计(3/9):创建表
查看>>
【C#】SQL数据库助手类1.0(自用)
查看>>
任意次序的n个烙饼最小反转次数求解
查看>>
C# 使用List泛型读取和保存文本文件
查看>>
EBS R12中的 APPLTMP , APPLPTMP, UTL_FILE_DIR 设置
查看>>
Qt之ui在程序中的使用——(2)多继承法
查看>>
C++ 文件操作(CFile类)
查看>>
基于jQuery的窗口插件:jMessageBox
查看>>
ReactNative环境搭建扩展篇——安装后报错解决方案
查看>>
手动备份
查看>>
【HeadFirst 设计模式学习笔记】1.策略模式
查看>>
给你的linux电脑跑个分(unixbench)
查看>>
souce insight出错 There was an error opening project
查看>>