Codechef A-Maxinum Score 思维题
2018-02-01 19:32
302 查看
题目简介:
You are given N integer sequences A1, A2, ..., AN. Each of these sequences contains N elements. You should pick N elements,
one from each sequence; let's denote the element picked from sequence Ai by Ei. For each i (2 ≤ i ≤ N), Ei should be strictly
greater than Ei-1.
Compute the maximum possible value of E1 + E2 + ... + EN. If it's impossible to pick the elements E1, E2, ..., EN,
print -1 instead.
The first line of each test case contains a single integer N.
N lines follow. For each valid i, the i-th of these lines contains N space-separated integers Ai1, Ai2, ..., AiN denoting the elements
of the sequence Ai.
1 ≤ N ≤ 700
1 ≤ sum of N in all test-cases ≤ 3700
1 ≤ Aij ≤ 109 for each valid i, j
Subtask #2 (82 points): original constraints
3+6+9 = 18.
这道题目就是给一个二维数组,每行选一个元素,从第一行开始严格递增,求选择的序列之和的最大值是多少。
我一开始以为是 dp , 结果一直 Time Limit Exceed , 700*700*700的操作.....
不好处理的就是,当前选好的递增序列可能在某一行,不能继续维持严格递增了,就要回去更改,在前一行选择另一个元素。。。。。最关键的就在最后一行了,最后一行的最大值一定是要选的,然后之前选择的值也一定要小于最后一行的最大值,这样就可以了,倒着加,从后面往前面找,在当前行选的 cur ,选择上一行的小于cur 的最大值,这样就保证严格递减( 从高往低 ) , 而且不用改。思维题。
注意数据类型 long long
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std ;
typedef long long LL ;
LL a[705][705] ;
int main(){
int T , n ;
scanf( "%d" , &T ) ;
while( T-- ){
scanf( "%d" , &n ) ;
int i , j , flag ;
for( i = 1 ; i <= n ; ++i ){
for( j = 1 ; j <= n ; ++j )
scanf( "%lld" , &a[i][j] ) ;
sort( a[i]+1 , a[i]+n+1 ) ; // 先排好序,从后面更大的开始筛选
}
LL ans = a
, cur = ans ;
for( i = n-1 ; i >= 1 ; --i ){ // 从高往低找
flag = 0 ;
for( j = n ; j >= 1 && a[i][j] >= cur ; --j ) ; // 找上一行小于 cur 的最大值
flag = a[i][j] < cur ;
if( flag ) // 如果找得到更小的最大值 , ans 累加,更新当前行最大值
ans += a[i][j] , cur = a[i][j] ;
else break ; // 在第 i 行找不到继续从高往低递减的值,序列不存在
}
printf( flag == 0 ? "-1\n" : "%lld\n" , ans ) ;
}
return 0 ;
}
我一开始就是用 dp 做的,自己测的简单数据都没错,然后一直超时,三重循环。我也不知道原来写的对不对,如有错误,敬请指正。(请忽略超时 ,emm)
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std ;
typedef long long LL ;
LL dp[705][705] , a[705][705] ;
bool cmp( LL a , LL b ){ return a > b ; }
int main(){
int T , n ;
scanf( "%d" , &T ) ;
while( T-- ){
memset( dp , 0 , sizeof( dp ) ) ;
scanf( "%d" , &n ) ;
int OK = 0 , i , j , k ;
for( i = 1 ; i <= n ; ++i ){
for( int j = 1 ; j <= n ; ++j )
scanf( "%lld" , &a[i][j] ) ;
aaf7
sort( a[i]+1 , a[i]+n+1 , cmp ) ;
}
for( i = 1 ; i <= n ; ++i ){ // 每一行
OK = 0 ;
for( j = 1 ; j <= n ; ++j ){ // 每一个元素
if( a[i][j] <= a[i-1]
) break ; // 后面的更没希望了
for( k = 1 ; k <= n ; ++k ) // 和上一行的元素做对比
if( ( i == 1 || dp[i-1][k] ) && a[i][j] > a[i-1][k] ) // 如果上一行的这个数在某个连续的递增序列中
dp[i][j] = max( dp[i][j] , dp[i-1][k] + a[i][j] ) , OK = 1 ;
}
if( !OK ) break ;
}
if( !OK ) { cout << "-1" << endl ; continue ; }
LL ans = dp
[1] ;
for( i = 2 ; i <= n ; ++i )
ans = max( ans , dp
[i] ) ;
printf( ans == 0 ? "-1\n" : "%lld\n" , ans ) ;
}
return 0 ;
}
You are given N integer sequences A1, A2, ..., AN. Each of these sequences contains N elements. You should pick N elements,
one from each sequence; let's denote the element picked from sequence Ai by Ei. For each i (2 ≤ i ≤ N), Ei should be strictly
greater than Ei-1.
Compute the maximum possible value of E1 + E2 + ... + EN. If it's impossible to pick the elements E1, E2, ..., EN,
print -1 instead.
Input
The first line of the input contains a single integer T denoting the number of test cases. The description of T test cases follows.The first line of each test case contains a single integer N.
N lines follow. For each valid i, the i-th of these lines contains N space-separated integers Ai1, Ai2, ..., AiN denoting the elements
of the sequence Ai.
Output
For each test case, print a single line containing one integer — the maximum sum of picked elements.Constraints
1 ≤ T ≤ 101 ≤ N ≤ 700
1 ≤ sum of N in all test-cases ≤ 3700
1 ≤ Aij ≤ 109 for each valid i, j
Subtasks
Subtask #1 (18 points): 1 ≤ Aij ≤ N for each valid i, jSubtask #2 (82 points): original constraints
Example
Input: 1 3 1 2 3 4 5 6 7 8 9 Output: 18
Explanation
Example case 1: To maximise the score, pick 3 from the first row, 6 from the second row and 9 from the third row. The resulting sum is E1+E2+E3 =3+6+9 = 18.
这道题目就是给一个二维数组,每行选一个元素,从第一行开始严格递增,求选择的序列之和的最大值是多少。
我一开始以为是 dp , 结果一直 Time Limit Exceed , 700*700*700的操作.....
不好处理的就是,当前选好的递增序列可能在某一行,不能继续维持严格递增了,就要回去更改,在前一行选择另一个元素。。。。。最关键的就在最后一行了,最后一行的最大值一定是要选的,然后之前选择的值也一定要小于最后一行的最大值,这样就可以了,倒着加,从后面往前面找,在当前行选的 cur ,选择上一行的小于cur 的最大值,这样就保证严格递减( 从高往低 ) , 而且不用改。思维题。
注意数据类型 long long
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std ;
typedef long long LL ;
LL a[705][705] ;
int main(){
int T , n ;
scanf( "%d" , &T ) ;
while( T-- ){
scanf( "%d" , &n ) ;
int i , j , flag ;
for( i = 1 ; i <= n ; ++i ){
for( j = 1 ; j <= n ; ++j )
scanf( "%lld" , &a[i][j] ) ;
sort( a[i]+1 , a[i]+n+1 ) ; // 先排好序,从后面更大的开始筛选
}
LL ans = a
, cur = ans ;
for( i = n-1 ; i >= 1 ; --i ){ // 从高往低找
flag = 0 ;
for( j = n ; j >= 1 && a[i][j] >= cur ; --j ) ; // 找上一行小于 cur 的最大值
flag = a[i][j] < cur ;
if( flag ) // 如果找得到更小的最大值 , ans 累加,更新当前行最大值
ans += a[i][j] , cur = a[i][j] ;
else break ; // 在第 i 行找不到继续从高往低递减的值,序列不存在
}
printf( flag == 0 ? "-1\n" : "%lld\n" , ans ) ;
}
return 0 ;
}
我一开始就是用 dp 做的,自己测的简单数据都没错,然后一直超时,三重循环。我也不知道原来写的对不对,如有错误,敬请指正。(请忽略超时 ,emm)
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std ;
typedef long long LL ;
LL dp[705][705] , a[705][705] ;
bool cmp( LL a , LL b ){ return a > b ; }
int main(){
int T , n ;
scanf( "%d" , &T ) ;
while( T-- ){
memset( dp , 0 , sizeof( dp ) ) ;
scanf( "%d" , &n ) ;
int OK = 0 , i , j , k ;
for( i = 1 ; i <= n ; ++i ){
for( int j = 1 ; j <= n ; ++j )
scanf( "%lld" , &a[i][j] ) ;
aaf7
sort( a[i]+1 , a[i]+n+1 , cmp ) ;
}
for( i = 1 ; i <= n ; ++i ){ // 每一行
OK = 0 ;
for( j = 1 ; j <= n ; ++j ){ // 每一个元素
if( a[i][j] <= a[i-1]
) break ; // 后面的更没希望了
for( k = 1 ; k <= n ; ++k ) // 和上一行的元素做对比
if( ( i == 1 || dp[i-1][k] ) && a[i][j] > a[i-1][k] ) // 如果上一行的这个数在某个连续的递增序列中
dp[i][j] = max( dp[i][j] , dp[i-1][k] + a[i][j] ) , OK = 1 ;
}
if( !OK ) break ;
}
if( !OK ) { cout << "-1" << endl ; continue ; }
LL ans = dp
[1] ;
for( i = 2 ; i <= n ; ++i )
ans = max( ans , dp
[i] ) ;
printf( ans == 0 ? "-1\n" : "%lld\n" , ans ) ;
}
return 0 ;
}
相关文章推荐
- CodeChef:Chef and Subsequences(思维 & dfs)
- CodeChef:Desik And Divisors(数学 & 二分 & 思维)
- CodeChef:A temple of Snakes(思维 & 二分)
- CodeChef - AMJMP Jump on Buildings 【dp + 思维】
- Codechef A temple of Snakes(思维)
- C - A Game of Balls CodeChef - GAMEBALL 思维模拟
- codechef Partition the numbers(思维)
- CodeChef:Magic Board(思维 & 树状数组)
- CodeChef:Two Closest(最短路 & 思维)
- CodeChef Add or Multiply 【思维】
- CodeChef - AMR16I Mancunian Hoards Black Money 【前缀 + 思维】
- codeforces Karen and Coffee (区间贡献 思维)
- BZOJ 4546|CodeChef XRQRS|Xor Queries|可持久化Trie
- CodeChef PRIMEDST Prime Distance On Tree
- 【CodeFores 948 】B【筛法+思维】C【树状数组+思维】
- CodeChef:Fombinatorial(数论 & 逆元)
- Codechef TREEPATH 线段树优化dp+dsu on tree
- CodeChef December Challenge 2013 解题报告
- CodeChef SEPT17 简要题解
- [分治最短路 && 树链剖分]Codechef September Challenge 2017 QGRID. Querying on a Grid