Codeforces 322D Ciel and Duel【思维+费用流】
2017-09-28 17:57
411 查看
D. Ciel and Duel
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
Fox Ciel is playing a card game with her friend Jiro.
Jiro has n cards, each one has two attributes: position (Attack
or Defense) and strength. Fox Ciel has m cards,
each one has these two attributes too. It's known that position of all Ciel's cards is Attack.
Now is Ciel's battle phase, Ciel can do the following operation many times:
Choose one of her cards X. This card mustn't be chosen before.
If Jiro has no alive cards at that moment, he gets the damage equal to (X's strength). Otherwise, Ciel needs to choose one Jiro's alive
card Y, then:
If Y's position is Attack, then (X's
strength) ≥ (Y's
strength) must hold. After this attack, card Y dies, and Jiro gets the damage equal to (X's
strength) - (Y's strength).
If Y's position is Defense, then (X's
strength) > (Y's
strength) must hold. After this attack, card Y dies, but Jiro gets no damage.
Ciel can end her battle phase at any moment (so, she can use not all her cards). Help the Fox to calculate the maximal sum of damage Jiro can get.
Input
The first line contains two integers n and m (1 ≤ n, m ≤ 100)
— the number of cards Jiro and Ciel have.
Each of the next n lines contains a string position and
an integer strength (0 ≤ strength ≤ 8000) —
the position and strength of Jiro's current card. Position is the string "ATK" for attack, and the string "DEF"
for defense.
Each of the next m lines contains an integer strength (0 ≤ strength ≤ 8000)
— the strength of Ciel's current card.
Output
Output an integer: the maximal damage Jiro can get.
Examples
input
output
input
output
input
output
Note
In the first test case, Ciel has 3 cards with same strength. The best strategy is as follows. First she uses one of these 3 cards to
attack "ATK 2000" card first, this attack destroys that card and Jiro gets 2500 - 2000 = 500 damage. Then she uses the second card to destroy
the "DEF 1700" card. Jiro doesn't get damage that time. Now Jiro has no cards so she can use the third card to attack and Jiro gets 2500damage.
So the answer is 500 + 2500 = 3000.
In the second test case, she should use the "1001" card to attack the "ATK 100" card, then use the "101" card to attack the "ATK 10" card. Now Ciel still has cards but she can choose to end her battle phase. The total damage equals (1001 - 100) + (101 - 10) = 992.
In the third test case note that she can destroy the "ATK 0" card by a card with strength equal to 0, but she can't destroy a "DEF 0" card with that card.
题目大意:
给出N个敌人,以及M个己方人物,每个人物都有一个能力值。
敌人有两种状态,一种是攻击状态,一种是防御状态。
我们的每个人物只能发起攻击一次。
对于攻击状态:我们如果有一个人物的能力值大于等于敌人的能力值,那么可以将其杀死并且能够获得差值的价值。
对于防御状态:我们如果有一个人物的能力值大于敌人的能力值,那么可以将其杀死,但是不会获得价值。
如果没有敌人的情况下,我们还有人物没有发起攻击,那么我们可以获得该人物的能力值的价值。
问怎样攻击敌人能够获得最多的价值。
思路:
考虑费用流/KM去做。
问题分成两种情况:
①n<=m,也就是说,我们不会剩下剩余多余的选手,那么建图方式如下:
1.建立源点,连入各个我方人物,流为1,花费为0.
2.建立汇点,将各个敌人连入汇点,流为1,花费为0.
3.如果我方人物能够击败敌方人物(攻击类型),流为1,花费为差值,
那么接下来跑个最大费用流就行。注意当前情况我们要的是可行流,不用跑满流,满流不一定最大费用。
②n>m,也就是说,我们可能剩下多余的选手,那么建图方式如下:
1.建立源点,连入各个我方人物,流为1,花费为0.
2.建立汇点,将各个敌人连入汇点,流为1,花费为0.
3.如果我方人物能够击败敌方人物(攻击类型),流为1,花费为差值,
4.如果我方人物不能够击败敌方人物(攻击类型),流为1,花费为负INF,
5.如果我方人物能够击败敌方人物(防御类型),流为1,0,
6.如果我方人物不能够击败敌方人物(防御类型),流为1,花费为负INF,
7.每个我方人物连入拓展节点(表示直接获得的价值),流为1,花费为每个人物的能力值。
那么我们接下来希望跑出最大费用最大流,因为只有最大流的时候,我们才允许我方人物直接获取价值,所以这里必须要跑满流。
两种情况取最大值即可。
Ac代码:
#include<stdio.h>
#include<string.h>
#include<map>
#include<iostream>
#include<queue>
using namespace std;
int output,d;
struct node
{
int from;
int to;
int w;
int f;
int num;
int next;
}e[2000000];
int head[150000];
int vis[150000];
int dis[150000];
int pre[150000];
int path[150000];
struct node2
{
char op[150];
int val;
}a[15000];
int n,ss,tt,cont,nn,mm;
void add(int from,int to,int f,int w)
{
e[cont].from=from;
e[cont].to=to;
e[cont].f=f;
e[cont].w=w;
e[cont].num=cont;
e[cont].next=head[from];
head[from]=cont++;
}
int SPFA()
{
memset(vis,0,sizeof(vis));
for(int i=1;i<=tt;i++)dis[i]=-0x3f3f3f3f;
dis[ss]=0;
queue<int >s;
s.push(ss);
while(!s.empty())
{
int u=s.front();
s.pop();
vis[u]=0;
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
int w=e[i].w;
int f=e[i].f;
if(f&&dis[v]<dis[u]+w)
{
dis[v]=dis[u]+w;
pre[v]=u;
path[v]=e[i].num;
if(vis[v]==0)
{
vis[v]=1;
s.push(v);
}
}
}
}
if(d==1)
{
if(dis[tt]>=0)return 1;
else return 0;
}
else
{
if(dis[tt]!=-0x3f3f3f3f)return 1;
else return 0;
}
}
void Slove()
{
d++;
int ans=0;
int maxflow=0;
while(SPFA()==1)
{
int minn=0x3f3f3f3f;
for(int i=tt;i!=ss;i=pre[i])
{
minn=min(minn,e[path[i]].f);
}
for(int i=tt;i!=ss;i=pre[i])
{
e[path[i]].f-=minn;
e[path[i]^1].f+=minn;
}
maxflow+=minn;
ans+=dis[tt]*minn;
}
// printf("---%d\n",ans);
output=max(output,ans);
}
int xx[150000];
int main()
{
while(~scanf("%d%d",&nn,&mm))
{
output=0,d=0;
ss=nn+mm+1;tt=nn+mm+2;
cont=0;
memset(head,-1,sizeof(head));
for(int i=1;i<=nn;i++)
{
scanf("%s%d",a[i].op,&a[i].val);
}
for(int i=1;i<=mm;i++)scanf("%d",&xx[i]);
for(int i=1;i<=mm;i++)add(ss,i,1,0),add(i,ss,0,0);
for(int i=1;i<=nn;i++)add(i+mm,tt,1,0),add(tt,i+mm,0,0);
for(int i=1;i<=mm;i++)
{
int x=xx[i];
for(int j=1;j<=nn;j++)
{
if(a[j].op[0]=='A'&&x>=a[j].val)
{
add(i,j+mm,1,x-a[j].val);
add(j+mm,i,0,-(x-a[j].val));
}
}
}
Slove();
if(nn<mm)
{
ss=mm*2+1;tt=ss+1;
cont=0;
memset(head,-1,sizeof(head));
for(int i=1;i<=mm;i++)add(ss,i,1,0),add(i,ss,0,0);
for(int i=1;i<=nn;i++)add(i+mm,tt,1,0),add(tt,i+mm,0,0);
for(int i=nn+1;i<=mm;i++)add(i+mm,tt,1,0),add(tt,i+mm,0,0);
for(int i=1;i<=mm;i++)
{
int x=xx[i];
for(int j=1;j<=nn;j++)
{
if(a[j].op[0]=='A')
{
if(x>=a[j].val)
{
add(i,j+mm,1,x-a[j].val);
add(j+mm,i,0,-(x-a[j].val));
}
else
{
add(i,j+mm,1,-10000000);
add(j+mm,i,0,10000000);
}
}
else
{
if(x>a[j].val)
{
add(i,j+mm,1,0);
add(j+mm,i,0,0);
}
else
{
add(i,j+mm,1,-10000000);
add(j+mm,i,0,10000000);
}
}
}
for(int j=nn+1;j<=mm;j++)
{
add(i,j+mm,1,xx[i]);
add(j+mm,i,0,-xx[i]);
}
}
Slove();
}
printf("%d\n",output);
}
}
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
Fox Ciel is playing a card game with her friend Jiro.
Jiro has n cards, each one has two attributes: position (Attack
or Defense) and strength. Fox Ciel has m cards,
each one has these two attributes too. It's known that position of all Ciel's cards is Attack.
Now is Ciel's battle phase, Ciel can do the following operation many times:
Choose one of her cards X. This card mustn't be chosen before.
If Jiro has no alive cards at that moment, he gets the damage equal to (X's strength). Otherwise, Ciel needs to choose one Jiro's alive
card Y, then:
If Y's position is Attack, then (X's
strength) ≥ (Y's
strength) must hold. After this attack, card Y dies, and Jiro gets the damage equal to (X's
strength) - (Y's strength).
If Y's position is Defense, then (X's
strength) > (Y's
strength) must hold. After this attack, card Y dies, but Jiro gets no damage.
Ciel can end her battle phase at any moment (so, she can use not all her cards). Help the Fox to calculate the maximal sum of damage Jiro can get.
Input
The first line contains two integers n and m (1 ≤ n, m ≤ 100)
— the number of cards Jiro and Ciel have.
Each of the next n lines contains a string position and
an integer strength (0 ≤ strength ≤ 8000) —
the position and strength of Jiro's current card. Position is the string "ATK" for attack, and the string "DEF"
for defense.
Each of the next m lines contains an integer strength (0 ≤ strength ≤ 8000)
— the strength of Ciel's current card.
Output
Output an integer: the maximal damage Jiro can get.
Examples
input
2 3 ATK 2000 DEF 1700 2500 2500 2500
output
3000
input
3 4 ATK 10 ATK 100 ATK 1000 1 11 101 1001
output
992
input
2 4 DEF 0 ATK 0 0 0 1 1
output
1
Note
In the first test case, Ciel has 3 cards with same strength. The best strategy is as follows. First she uses one of these 3 cards to
attack "ATK 2000" card first, this attack destroys that card and Jiro gets 2500 - 2000 = 500 damage. Then she uses the second card to destroy
the "DEF 1700" card. Jiro doesn't get damage that time. Now Jiro has no cards so she can use the third card to attack and Jiro gets 2500damage.
So the answer is 500 + 2500 = 3000.
In the second test case, she should use the "1001" card to attack the "ATK 100" card, then use the "101" card to attack the "ATK 10" card. Now Ciel still has cards but she can choose to end her battle phase. The total damage equals (1001 - 100) + (101 - 10) = 992.
In the third test case note that she can destroy the "ATK 0" card by a card with strength equal to 0, but she can't destroy a "DEF 0" card with that card.
题目大意:
给出N个敌人,以及M个己方人物,每个人物都有一个能力值。
敌人有两种状态,一种是攻击状态,一种是防御状态。
我们的每个人物只能发起攻击一次。
对于攻击状态:我们如果有一个人物的能力值大于等于敌人的能力值,那么可以将其杀死并且能够获得差值的价值。
对于防御状态:我们如果有一个人物的能力值大于敌人的能力值,那么可以将其杀死,但是不会获得价值。
如果没有敌人的情况下,我们还有人物没有发起攻击,那么我们可以获得该人物的能力值的价值。
问怎样攻击敌人能够获得最多的价值。
思路:
考虑费用流/KM去做。
问题分成两种情况:
①n<=m,也就是说,我们不会剩下剩余多余的选手,那么建图方式如下:
1.建立源点,连入各个我方人物,流为1,花费为0.
2.建立汇点,将各个敌人连入汇点,流为1,花费为0.
3.如果我方人物能够击败敌方人物(攻击类型),流为1,花费为差值,
那么接下来跑个最大费用流就行。注意当前情况我们要的是可行流,不用跑满流,满流不一定最大费用。
②n>m,也就是说,我们可能剩下多余的选手,那么建图方式如下:
1.建立源点,连入各个我方人物,流为1,花费为0.
2.建立汇点,将各个敌人连入汇点,流为1,花费为0.
3.如果我方人物能够击败敌方人物(攻击类型),流为1,花费为差值,
4.如果我方人物不能够击败敌方人物(攻击类型),流为1,花费为负INF,
5.如果我方人物能够击败敌方人物(防御类型),流为1,0,
6.如果我方人物不能够击败敌方人物(防御类型),流为1,花费为负INF,
7.每个我方人物连入拓展节点(表示直接获得的价值),流为1,花费为每个人物的能力值。
那么我们接下来希望跑出最大费用最大流,因为只有最大流的时候,我们才允许我方人物直接获取价值,所以这里必须要跑满流。
两种情况取最大值即可。
Ac代码:
#include<stdio.h>
#include<string.h>
#include<map>
#include<iostream>
#include<queue>
using namespace std;
int output,d;
struct node
{
int from;
int to;
int w;
int f;
int num;
int next;
}e[2000000];
int head[150000];
int vis[150000];
int dis[150000];
int pre[150000];
int path[150000];
struct node2
{
char op[150];
int val;
}a[15000];
int n,ss,tt,cont,nn,mm;
void add(int from,int to,int f,int w)
{
e[cont].from=from;
e[cont].to=to;
e[cont].f=f;
e[cont].w=w;
e[cont].num=cont;
e[cont].next=head[from];
head[from]=cont++;
}
int SPFA()
{
memset(vis,0,sizeof(vis));
for(int i=1;i<=tt;i++)dis[i]=-0x3f3f3f3f;
dis[ss]=0;
queue<int >s;
s.push(ss);
while(!s.empty())
{
int u=s.front();
s.pop();
vis[u]=0;
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
int w=e[i].w;
int f=e[i].f;
if(f&&dis[v]<dis[u]+w)
{
dis[v]=dis[u]+w;
pre[v]=u;
path[v]=e[i].num;
if(vis[v]==0)
{
vis[v]=1;
s.push(v);
}
}
}
}
if(d==1)
{
if(dis[tt]>=0)return 1;
else return 0;
}
else
{
if(dis[tt]!=-0x3f3f3f3f)return 1;
else return 0;
}
}
void Slove()
{
d++;
int ans=0;
int maxflow=0;
while(SPFA()==1)
{
int minn=0x3f3f3f3f;
for(int i=tt;i!=ss;i=pre[i])
{
minn=min(minn,e[path[i]].f);
}
for(int i=tt;i!=ss;i=pre[i])
{
e[path[i]].f-=minn;
e[path[i]^1].f+=minn;
}
maxflow+=minn;
ans+=dis[tt]*minn;
}
// printf("---%d\n",ans);
output=max(output,ans);
}
int xx[150000];
int main()
{
while(~scanf("%d%d",&nn,&mm))
{
output=0,d=0;
ss=nn+mm+1;tt=nn+mm+2;
cont=0;
memset(head,-1,sizeof(head));
for(int i=1;i<=nn;i++)
{
scanf("%s%d",a[i].op,&a[i].val);
}
for(int i=1;i<=mm;i++)scanf("%d",&xx[i]);
for(int i=1;i<=mm;i++)add(ss,i,1,0),add(i,ss,0,0);
for(int i=1;i<=nn;i++)add(i+mm,tt,1,0),add(tt,i+mm,0,0);
for(int i=1;i<=mm;i++)
{
int x=xx[i];
for(int j=1;j<=nn;j++)
{
if(a[j].op[0]=='A'&&x>=a[j].val)
{
add(i,j+mm,1,x-a[j].val);
add(j+mm,i,0,-(x-a[j].val));
}
}
}
Slove();
if(nn<mm)
{
ss=mm*2+1;tt=ss+1;
cont=0;
memset(head,-1,sizeof(head));
for(int i=1;i<=mm;i++)add(ss,i,1,0),add(i,ss,0,0);
for(int i=1;i<=nn;i++)add(i+mm,tt,1,0),add(tt,i+mm,0,0);
for(int i=nn+1;i<=mm;i++)add(i+mm,tt,1,0),add(tt,i+mm,0,0);
for(int i=1;i<=mm;i++)
{
int x=xx[i];
for(int j=1;j<=nn;j++)
{
if(a[j].op[0]=='A')
{
if(x>=a[j].val)
{
add(i,j+mm,1,x-a[j].val);
add(j+mm,i,0,-(x-a[j].val));
}
else
{
add(i,j+mm,1,-10000000);
add(j+mm,i,0,10000000);
}
}
else
{
if(x>a[j].val)
{
add(i,j+mm,1,0);
add(j+mm,i,0,0);
}
else
{
add(i,j+mm,1,-10000000);
add(j+mm,i,0,10000000);
}
}
}
for(int j=nn+1;j<=mm;j++)
{
add(i,j+mm,1,xx[i]);
add(j+mm,i,0,-xx[i]);
}
}
Slove();
}
printf("%d\n",output);
}
}
相关文章推荐
- 网络流(费用流)CodeForces 321B:Ciel and Duel
- Codeforces 322C Ciel and Robot【思维+模拟】细节很多= =
- Codeforces 682C Alyona and the Tree【Dfs+YY思维】好题
- Codeforces 518C Anya and Smartphone【思维+模拟】
- CF:322D - Ciel and Duel 贪心 或者 DP 我用的贪心 。。难道sort跟qsort是不一样的么?
- 【Codeforces 756 D. Artsem and Saunders】+ 思维 + 构造
- CodeForces - 296D.Greg and Graph(Floyd+逆序思维)
- Codeforces 340E Iahub and Permutations【思维+错排Dp】
- codeforces 714C Sonya and Queries [思维]【STL】
- CodeForces - 610A-G - Pasha and Stick-思维
- Codeforces 594A - Warrior and Archer (思维)
- CodeForces 552C-Vanya and Scales【思维】
- CodeForces - 361C A - Levko and Array Recovery 思维
- codeforces 768C Jon Snow and his Favourite Number 【思维】
- Codeforces400E - Inna and Binary Logic - 思维、数学
- codeforces 321E Ciel and Gondolas 四边形不等式
- CodeForces 748C Santa Claus and Robot (思维)
- codeforces-Fox And Two Dots【DFS】(思维)
- hihocoder#1529 : 不上升序列&&Codeforces-713C:Sonya and Problem Wihtout a Legend(思维)
- CodeForces 288C - Polo the Penguin and XOR operation(思维)