ACM-ICPC 2018 南京赛区网络预赛 AC Challenge (状态压缩+暴力)

Dlsj is competing in a contest with n(0<n≤20)n (0 < n \le 20)n(0<n≤20) problems. And he knows the answer of all of these problems.

However, he can submit iii-th problem if and only if he has submitted (and passed, of course) sis_isi​ problems, the pi,1p_{i, 1}pi,1​-th, pi,2p_{i, 2}pi,2​-th, ........., pi,sip_{i, s_i}pi,si​​-th problem before.(0<pi,j≤n,0<j≤si,0<i≤n)(0 < p_{i, j} \le n,0 < j \le s_i,0 < i \le n)(0<pi,j​≤n,0<j≤si​,0<i≤n) After the submit of a problem, he has to wait for one minute, or cooling down time to submit another problem. As soon as the cooling down phase ended, he will submit his solution (and get "Accepted" of course) for the next problem he selected to solve or he will say that the contest is too easy and leave the arena.

"I wonder if I can leave the contest arena when the problems are too easy for me."
"No problem."
—— CCF NOI Problem set

If he submits and passes the iii-th problem on ttt-th minute(or the ttt-th problem he solve is problem iii), he can get t×ai+bit \times a_i + b_it×ai​+bi​ points. (∣ai∣,∣bi∣≤109)(|a_i|, |b_i| \le 10^9)(∣ai​∣,∣bi​∣≤109).

Your task is to calculate the maximum number of points he can get in the contest.

Input

The first line of input contains an integer, nnn, which is the number of problems.

Then follows nnn lines, the iii-th line contains si+3s_i + 3si​+3 integers, ai,bi,si,p1,p2,...,psia_i,b_i,s_i,p_1,p_2,...,p_{s_i}ai​,bi​,si​,p1​,p2​,...,psi​​as described in the description above.

Output

Output one line with one integer, the maximum number of points he can get in the contest.

Hint

In the first sample.

On the first minute, Dlsj submitted the first problem, and get 1×5+6=111 \times 5 + 6 = 111×5+6=11 points.

On the second minute, Dlsj submitted the second problem, and get 2×4+5=132 \times 4 + 5 = 132×4+5=13 points.

On the third minute, Dlsj submitted the third problem, and get 3×3+4=133 \times 3 + 4 = 133×3+4=13 points.

On the forth minute, Dlsj submitted the forth problem, and get 4×2+3=114 \times 2 + 3 = 114×2+3=11 points.

On the fifth minute, Dlsj submitted the fifth problem, and get 5×1+2=75 \times 1 + 2 = 75×1+2=7 points.

So he can get 11+13+13+11+7=5511+13+13+11+7=5511+13+13+11+7=55 points in total.

In the second sample, you should note that he doesn't have to solve all the problems.

样例输入1复制

5
5 6 0
4 5 1 1
3 4 1 2
2 3 1 3
1 2 1 4

样例输出1复制

55

样例输入2复制

1
-100 0 0

样例输出2复制

0

题目来源

ACM-ICPC 2018 南京赛区网络预赛

代码高亮 Sublime Vim Emacs

环境配色亮色配色暗色配色 暗色配色

返回

  • 亮色配色
  • 暗色配色

代码缩进248 4

返回

  • 2
  • 4
  • 8

C 语言C++ 语言 (C++11)Java 语言 C++ 语言 (C++11)

返回

  • C 语言
  • C++ 语言 (C++11)
  • Java 语言
  • main.cpp

通用

逻辑

循环

数学

文本

列表

颜色

变量

函数

 

 

69

        if((has&sta[i])==sta[i]) dfs(has|(1<<i),t+1,v+1LL*a[i]*t+1LL*b[i]);///满足前提的情况下

 

49

    }

50

51

    ///for(int i=0;i<n;i++) cout<<sta[i]<<endl;

52

53

    memset(dp,-1,sizeof(dp));

54

    ans=0;

55

    dfs(0,1,0);

56

    for(int i=0;i<(1<<n);i++) ans=max(ans,dp[i]);

57

    printf("%lld\n",ans);

58

59

    return 0;

60

}

61

/*

62

5

63

5 6 0

64

4 5 1 1

65

3 4 1 2

66

2 3 1 3

67

1 2 1 4

68

*/

69

关闭终端 终端 - 计蒜客

只看题面

 

 

#pragma comment(linker, "/STACK:102400000,102400000")
#include<bits/stdc++.h>
using namespace std;
#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define ll long long
const int  maxn =3e3+5;
const int mod=1e9+7;
ll gcd(ll x,ll y){return y==0?x:gcd(y,x%y);}
ll powmod(ll x,ll y){ll t;for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod;return t;}
/*
题目大意:做题目,
一个拓扑图,每道题目的权重根据做到当前题目的时间而定,
求最优权重。

一看数据量状压没跑了。状压+搜索敲定,本人比赛时由于好久没刷这类型题目了,
居然TMD多想了个状态,就是可达领域的状态,,,天呐,,不是说好的DFS大暴力的嘛。
虽然不影响但是浪费了超多时间。

这道题思维清楚的话可以秒,代码一点也不难。
就是有些小思维点,想清楚就行了。
首先DFS中记录了当前的状态,就是已经走过的点,
然后下面延扩要探索到能走到的点,
判断条件是用位运算代替。
最后用dp数组剪下枝即可。
因为同一个状态数的话,总时间是一样的,产生的权重不同是
因为选择顺序的不同。这样判定数组就可以有效的剪枝。
利用状态压缩暴力枚举就行了。
*/
///数据域
int n,q,x;
int a[24],b[24];
int sta[24];
///dp与答案
ll dp[1<<21];///状态最优方案
ll ans=0;
void dfs(int has,int t,ll v)
{
    if(dp[has]<v||dp[has]==-1) dp[has]=v;
    else return ;
    for(int i=0;i<n;i++)
    {
        if(has&(1<<i)) continue;///如果已经走过没必要再走
        if((has&sta[i])==sta[i])
            dfs(has|(1<<i),t+1,v+1LL*a[i]*t+1LL*b[i]);///满足前提的情况下
    }
}

int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%d%d",&a[i],&b[i]);
        scanf("%d",&q);
        for(int j=0;j<q;j++)
        {
            scanf("%d",&x);x--;
            sta[i]+=(1<<x);///到达i的条件
        }
    }
    memset(dp,-1,sizeof(dp));ans=0;
    dfs(0,1,0);
    for(int i=0;i<(1<<n);i++) ans=max(ans,dp[i]);
    printf("%lld\n",ans);
    return 0;
}
/*
5
5 6 0
4 5 1 1
3 4 1 2
2 3 1 3
1 2 1 4
*/

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值