[HNOI 2017] 보스.
이 문제는 매우 묘하다고 생각한다. 제목은 매일 그렇게 많은 선택이 있다고 말하지만 사실은 죽지 않는다면 가장 큰 상처를 매거할 수 있고 죽지 않으면 DP도 할 수 있다.구체적으로 말하면 먼저 죽지 않을 것을 보장해야 한다. 그러면 우리는 dp[i][j]를 설정하면 전 i일, 제 i일의 자신감치가 j이다. 그러면 전 i일 중 최대 며칠 동안 문제를 풀지 않아도 된다. 즉, 상처를 입힐 수 있다.사실 모든 상태가 열거된 누드 DP에 해당한다.이 단계를 마치면, 우리는 dp수 그룹의 최대 값을 얻는다. 즉, 내가 최대 며칠 동안 사용할 수 있는지.D일을 가정해 보세요.D일에서 3, 4, 5를 선택하면 되고 나머지 일수는 다퇴소보하며 1을 적당히 하면 된다.두 번 헐뜯는 경우는 각각 (d1,f1),(d2,f2), 즉 며칠을 들여 상처를 입히는 것이다.만약에 큰 놈의 생명이 HP라고 가정하면 HP-f1-f2>=0이다. 그렇지 않으면 큰 놈의 생명치가 마이너스가 되고 죽일 수 있는 것을 만족시켜야 한다. 즉, HP-f1-f2<=D-d1-d2, 즉 큰 놈의 남은 생명은 내가 남은 일수에서 1조작을 수행하여 끝낼 수 있다.물론 이것은 두 번의 상황이다. 한 번은 HP-f1>=0 & HP-f1<=D-d1이면 되고, 헐뜯지 않으면 HP>=0 & HP<=D면 된다.조건에 맞는 것만 있으면 1.우리 bfs+무게 판정 매개체는 가능한 모든 (d, f) 를 들고 f를 첫 번째 키워드로 하고 d를 두 번째 키워드로 정렬합니다.f가 크고 작은 매거진에 따라 첫 번째 헐뜯은 다음에 이것이 단조로운 것을 발견했다. 우리는 항목 D>=HP-f1+d1-f2+d2, f1, d1을 매거진했다. 그러면 자연-f1+d2가 가장 작으면 된다.그러면 f1+f2<=HP를 만족시키는 조건에서 f2를 증대시키고, 즉 바늘을 뒤로 쓸고, 매번 -f1+d2를 가장 작게 뽑은 다음에 비교하고, O(상태수)를 쓸어버리면 된다.
1 #include
2 #include
3 #include
4 #include
5 #include
6 #define LL long long
7 #define pa pair
8 using namespace std;
9 const int MAXN=2100000,mod=3587201;
10 pa Q[MAXN];
11 int n,m,mc,D,MAXC,tp,Maxsize;
12 int dp[105][105],a[105],w[105],C[105];
13 struct ed {int step,F,L;};
14 queueQue;
15 struct ED
16 {
17 struct gg{int x,y,Next;}edge[MAXN];
18 int top,head[mod+5];
19 void insert(int x,int y)
20 {
21 int tmp=((LL)x*100+y)%mod;
22 edge[++top]=(gg){x,y,head[tmp]};head[tmp]=top;
23 }
24 bool query(int x,int y)
25 {
26 int tmp=((LL)x*100+y)%mod;
27 for(int i=head[tmp];i;i=edge[i].Next)
28 if(x==edge[i].x&&y==edge[i].y)return 1;
29 return 0;
30 }
31 }map;// map,Hash
32 inline int gi() { int res; scanf("%d",&res); return res; }
33 void prepare()
34 {
35 for(int i=1;i<=n;i++)
36 for(int j=a[i];j<=mc;j++)
37 {
38 dp[i][j-a[i]]=max(dp[i][j-a[i]],dp[i-1][j]+1);
39 int tmp=min(mc,j-a[i]+w[i]);
40 dp[i][tmp]=max(dp[i][tmp],dp[i-1][j]);
41 }
42 for(int i=1;i<=n;i++)
43 for(int j=0;j<=mc;j++)
44 D=max(D,dp[i][j]);
45 }
46 void bfs()
47 {
48 Que.push((ed){1,1,0});// : , 1 , 0。
49 while(!Que.empty())
50 {
51 ed now=Que.front();
52 Que.pop();
53 if(now.step<D)
54 {
55 Que.push((ed){now.step+1,now.F,now.L+1});// 1
56 if(now.L>1 && (LL)now.F*now.L<=(LL)MAXC && !map.query(now.F*now.L,now.step+1))// int,hash 。
57 {
58 ed tmp=(ed){now.step+1,now.F*now.L,now.L};
59 Que.push(tmp);
60 Q[++tp]=(pa){tmp.F,tmp.step};// , Que , , , 。
61 map.insert(tmp.F,tmp.step);
62 }
63 }
64 }
65 }
66 int main()
67 {
68 freopen("dalao.in","r",stdin);
69 freopen("dalao.out","w",stdout);
70 n=gi();m=gi();mc=gi();
71 for(int i=1;i<=n;i++)a[i]=gi();
72 for(int i=1;i<=n;i++)w[i]=gi();
73 for(int i=1;i<=m;i++)C[i]=gi(),MAXC=max(MAXC,C[i]);
74 prepare(); bfs();
75 sort(Q+1,Q+tp+1);
76 for(int i=1;i<=m;i++)
77 {
78 if(C[i]<=D) {puts("1"); continue;}
79 int flag=0,mi=0x3f3f3f3f;
80 for(int j=tp,k=1;j>=1;j--)// 。
81 {
82 while(k;
83 if(mi+Q[j].second-Q[j].first+C[i]<=D) {flag=1; break;}
84 if(Q[j].first<=C[i] && C[i]-Q[j].first+Q[j].second<=D) {flag=1; break;}
85 }
86 printf("%d
",flag);
87 }
88 return 0;
89 }
전재 대상:https://www.cnblogs.com/D-O-Time/p/7953435.html
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.