记 2024/4/16
P5365
[SNOI2017] 英雄联盟
题目描述
正在上大学的小皮球热爱英雄联盟这款游戏,而且打的很菜,被网友们戏称为「小学生」。
现在,小皮球终于受不了网友们的嘲讽,决定变强了,他变强的方法就是:买皮肤!
小皮球只会玩 个英雄,因此,他也只准备给这 个英雄买皮肤,并且决定,以后只玩有皮肤的英雄。
这 个英雄中,第 个英雄有 款皮肤,价格是每款 Q 币(同一个英雄的皮肤价格相同)。
为了让自己看起来高大上一些,小皮球决定给同学们展示一下自己的皮肤,展示的思路是这样的:对于有皮肤的每一个英雄,随便选一个皮肤给同学看。
比如,小皮球共有 5 个英雄,这 5 个英雄分别有 款皮肤,那么,小皮球就有 种展示的策略。
现在,小皮球希望自己的展示策略能够至少达到 种,请问,小皮球至少要花多少钱呢?
输入格式
第一行,两个整数 。
第二行, 个整数,表示每个英雄的皮肤数量 。
第三行, 个整数,表示每个英雄皮肤的价格 。
输出格式
一个整数,表示小皮球达到目标最少的花费。
样例 #1
样例输入 #1
3 24
4 4 4
2 2 2
样例输出 #1
18
提示
样例解释
每一个英雄都只有4款皮肤,每款皮肤2 Q币,那么每个英雄买3款皮肤,,共花费 Q币。
数据范围
共 10 组数据,第 组数据满足:
的数据:。保证有解。
依然是背包,根据背包 MAX 的性质,选用花费来作状态。且如果将方案做状态,,是绝对存不下的。
状态转移方程
表示目前枚举选几个 物品, 表示枚举的代价。
答案为 。
Code
#include <iostream>
#define int long long
using namespace std;
const int N=140;
int f[3010*N];
int w[N],s[N];
int n,kk,m;
signed main()
{
cin>>n>>kk;
f[0]=1;
for(int i=1;i<=n;i++) cin>>s[i];
for(int i=1;i<=n;i++) cin>>w[i],m+=s[i]*w[i];
for(int i=1;i<=n;i++)
for(int j=m;j>=0;j--)
for(int k=1;k<=s[i];k++)
if(j-w[i]*k>=0)
f[j]=max(f[j],f[j-w[i]*k]*k);
for(int i=0;;i++)//必有解
if(f[i]>=kk) {
cout<<i;
break;
}
return 0;
}
P3033
[USACO11NOV] Cow Steeplechase G
题目描述
Farmer John has a brilliant idea for the next great spectator sport: Cow Steeplechase! As everyone knows, regular steeplechase involves a group of horses that race around a course filled with obstacles they must jump over. FJ figures the same contest should work with highly-trained cows, as long as the obstacles are made short enough.
In order to design his course, FJ makes a diagram of all the N (1 <= N <= 250) possible obstacles he could potentially build. Each one is represented by a line segment in the 2D plane that is parallel to the horizontal or vertical axis. Obstacle i has distinct endpoints (X1_i, Y1_i) and (X2_i, Y2_i) (1 <= X1_i, Y1_i, X2_i, Y2_i <= 1,000,000,000). An example is as follows:
--+-------
-----+-----
---+--- |
| | |
--+-----+--+- |
| | | | |
| --+--+--+-+-
| | | |
|
FJ would like to build as many of these obstacles as possible, subject to the constraint that no two of them intersect. Starting with the diagram above, FJ can build 7 obstacles:
----------
-----------
------- |
| |
| | |
| | | |
| | | |
| | | |
|
Two segments are said to intersect if they share any point in common, even an endpoint of one or both of the segments. FJ is certain that no two horizontal segments in the original input diagram will intersect, and that similarly no two vertical segments in the input diagram will intersect.
Please help FJ determine the maximum number of obstacles he can build.
给出 条平行于坐标轴的线段,要你选出尽量多的线段使得这些线段两两没有交点(顶点也算)。横的与横的,竖的与竖的线段之间保证没有交点,输出最多能选出多少条线段。
输入格式
* Line 1: A single integer: N.
* Lines 2..N+1: Line i+1 contains four space-separated integers representing an obstacle: X1_i, Y1_i, X2_i, and Y2_i.
输出格式
* Line 1: The maximum number of non-crossing segments FJ can choose.
样例 #1
样例输入 #1
3
4 5 10 5
6 2 6 12
8 3 8 5
样例输出 #1
2
提示
There are three potential obstacles. The first is a horizontal segment connecting (4, 5) to (10, 5); the second and third are vertical segments connecting (6, 2) to (6, 12) and (8, 3) to (8, 5).
The optimal solution is to choose both vertical segments.
两条横竖线重叠,产生一个交点,相当于二分图两个部的点连边。因为两条线只能选一个,所以最大匹配就是最少要移除的点,于是 即为答案。
注意二选一问题可以抽象成二分图匹配。
Code
#include <iostream>
#include <cstring>
using namespace std;
const int N=1010,M=1e5+10;
int h[N],e[M],ne[M],idx,a[N];
int x1[N],y1[N],x2[N],y2[N];
bool st[N];
int match[N];
int n,n1,n2,m,ans;
void add(int a,int b)
{
e[idx]=b;
ne[idx]=h[a];
h[a]=idx++;
}
bool find(int x)
{
for(int i=h[x];i!=-1;i=ne[i])
{
int j=e[i];
if(!st[j])
{
st[j]=1;
if(match[j]==0||find(match[j]))
{
match[j]=x;
return 1;
}
}
}
return 0;
}
int main()
{
memset(h,-1,sizeof h);
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>x1[i]>>y1[i]>>x2[i]>>y2[i];
if(x1[i]>x2[i]) swap(x1[i],x2[i]);
if(y1[i]>y2[i]) swap(y1[i],y2[i]);
if(x1[i]==x2[i]) a[i]=1,n1++;
else a[i]=2;
}
for(int i=1;i<n;i++)
{
for(int j=i+1;j<=n;j++)
{
if(a[i]==1&&a[j]==2)
if(x1[j]<=x1[i]&&x2[j]>=x2[i]&&y1[i]<=y1[j]&&y2[j]<=y2[i])
add(i,j+n1);
if(a[i]==2&&a[j]==1)
if(x1[i]<=x1[j]&&x2[i]>=x2[j]&&y1[j]<=y1[i]&&y2[i]<=y2[j])
add(j,i+n1);
}
}
for(int i=1;i<=n;i++)
{
if(a[i]==2) continue;
memset(st,0,sizeof st);
if(find(i)) ans++;
}
cout<<n-ans;
return 0;
}

浙公网安备 33010602011771号