P2895 [USACO08FEB] Meteor Shower S
题目描述
贝茜听说一场特别的流星雨即将到来:这些流星会撞向地球,并摧毁它们所撞击的任何东西。她为自己的安全感到焦虑,发誓要找到一个安全的地方(一个永远不会被流星摧毁的地方)。
如果将牧场放入一个直角坐标系中,贝茜现在的位置是原点,并且,贝茜不能踏上一块被流星砸过的土地。
根据预报,一共有 M 颗流星 (1≤M≤50,000) 会坠落在农场上,其中第 i 颗流星会在时刻 Ti(0≤Ti≤1000)砸在坐标为 (Xi,Yi)(0≤Xi≤300,0≤Yi≤300) 的格子里。流星的力量会将它所在的格子,以及周围 4 个相邻的格子都化为焦土,当然贝茜也无法再在这些格子上行走。
贝茜在时刻 0 开始行动,她只能在会在横纵坐标 X,Y≥0 的区域中,平行于坐标轴行动,每 1 个时刻中,她能移动到相邻的(一般是 4 个)格子中的任意一个,当然目标格子要没有被烧焦才行。如果一个格子在时刻 t 被流星撞击或烧焦,那么贝茜只能在 t 之前的时刻在这个格子里出现。 贝茜一开始在 (0,0)。
请你计算一下,贝茜最少需要多少时间才能到达一个安全的格子。如果不可能到达输出 −1。
输入格式
共 M+1 行,第 1 行输入一个整数 M,接下来的 M 行每行输入三个整数分别为 Xi,Yi,Ti。
输出格式
贝茜到达安全地点所需的最短时间,如果不可能,则为 −1。
显示翻译
题意翻译
输入输出样例
输入 #1复制
4
0 0 2
2 1 2
1 1 2
0 3 5
输出 #1复制
5
实现代码:
cpp
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int m,map[350][350],f[350][350],ans=2147483647;
void dfs(int x,int y,int t){
if(map[x][y]<=t||t>=ans||t>=f[x][y])
return ;
f[x][y]=t;
if(map[x][y]>2100000000){
ans=min(t,ans);
return;
}
dfs(x+1,y,t+1);
if(x-1>=0) dfs(x-1,y,t+1);
dfs(x,y+1,t+1);
if(y-1>=0) dfs(x,y-1,t+1);
}
int main(){
memset(map,0x7f,sizeof(map));
memset(f,0xa7f,sizeof(f));
scanf("%d",&m);
for(int i=1;i<=m;i++){
int x,y,t;
scanf("%d %d %d",&x,&y,&t);
map[x][y]=min(map[x][y],t);
map[x+1][y]=min(map[x+1][y],t);
if(x-1>=0)
map[x-1][y]=min(map[x-1][y],t);
map[x][y+1]=min(map[x][y+1],t);
if(y-1>=0)
map[x][y-1]=min(map[x][y-1],t);
}
dfs(0,0,0);
if(ans==2147483647)
printf("-1");
else
printf("%d",ans);
return 0;
}
P1036 [NOIP 2002 普及组] 选数
题目描述
已知 n 个整数 x1,x2,⋯,xn,以及 1 个整数 k(k<n)。从 n 个整数中任选 k 个整数相加,可分别得到一系列的和。例如当 n=4,k=3,4 个整数分别为 3,7,12,19 时,可得全部的组合与它们的和为:
3+7+12=22
3+7+19=29
7+12+19=38
3+12+19=34
现在,要求你计算出和为素数共有多少种。
例如上例,只有一种的和为素数:3+7+19=29。
输入格式
第一行两个空格隔开的整数 n,k(1≤n≤20,k<n)。
第二行 n 个整数,分别为 x1,x2,⋯,xn(1≤xi≤5×106)。
输出格式
输出一个整数,表示种类数。
输入输出样例
输入 #1复制
4 3
3 7 12 19
输出 #1复制
1
说明/提示
【题目来源】
NOIP 2002 普及组第二题
实现代码:
cpp
#include<bits/stdc++.h>
using namespace std;
int a[33],ax[33];
int n,k,cnt;
int fun(int x){
for(int i=2;i*i<=x;i++){
if(x%i==0){
return 0;
}
}
return 1;
}
void dfs(int x,int sum,int y){
if(y==k){
if(fun(sum)==1){
cnt++;
}
return ;
}
for(int i=x+1;i<=n;i++){
if(ax[i]==0){
ax[i]=1;
dfs(i,sum+a[i],y+1);
ax[i]=0;
}
}
return;
}
int main(){
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>a[i];
}
dfs(0,0,0);
cout<<cnt;
return 0;
}
P2036 [COCI 2008/2009 #2] PERKET
题目描述
Perket 是一种流行的美食。为了做好 Perket,厨师必须谨慎选择食材,以在保持传统风味的同时尽可能获得最全面的味道。你有 n 种可支配的配料。对于每一种配料,我们知道它们各自的酸度 s 和苦度 b。当我们添加配料时,总的酸度为每一种配料的酸度总乘积;总的苦度为每一种配料的苦度的总和。
众所周知,美食应该做到口感适中,所以我们希望选取配料,以使得酸度和苦度的绝对差最小。
另外,我们必须添加至少一种配料,因为没有任何食物是只以水为配料的。
输入格式
第一行一个整数 n,表示可供选用的食材种类数。
接下来 n 行,每行 2 个整数 si 和 bi,表示第 i 种食材的酸度和苦度。
输出格式
一行一个整数,表示可能的总酸度和总苦度的最小绝对差。
输入输出样例
输入 #1复制
1
3 10
输出 #1复制
7
输入 #2复制
2
3 8
5 8
输出 #2复制
1
输入 #3复制
4
1 7
2 6
3 8
4 9
输出 #3复制
1
说明/提示
对于第三组样例,选择最后三种食材,此时的总酸度为 2×3×4=24,总苦度为 6+8+9=23,差值为 1。
数据规模与约定
对于 100% 的数据,有 1≤n≤10,且将所有可用食材全部使用产生的总酸度和总苦度小于 1×109。
说明
- 本题满分 70 分。
- 题目译自 COCI2008-2009 CONTEST #2 PERKET,译者 @mnesia。
附件下载
contest2_tasks.pdf101.88KB
实现代码:
cpp
#include<bits/stdc++.h>
using namespace std;
int n;
int s[15],b[15];
int c=1e9;
void dfs(int suan,int ku,int num){
if(num==n){
if(ku!=0){
c=min(c,abs(suan-ku));
}
return;
}
num++;
dfs(suan*s[num],ku+b[num],num);
dfs(suan,ku,num);
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>s[i]>>b[i];
}
dfs(1,0,0);
cout<<c;
return 0;
}
P1433 吃奶酪
题目描述
房间里放着 n 块奶酪。一只小老鼠要把它们都吃掉,问至少要跑多少距离?老鼠一开始在 (0,0) 点处。
输入格式
第一行有一个整数,表示奶酪的数量 n。
第 2 到第 (n+1) 行,每行两个实数,第 (i+1) 行的实数分别表示第 i 块奶酪的横纵坐标 xi,yi。
输出格式
输出一行一个实数,表示要跑的最少距离,保留 2 位小数。
输入输出样例
输入 #1复制
4
1 1
1 -1
-1 1
-1 -1
输出 #1复制
7.41
说明/提示
数据规模与约定
对于全部的测试点,保证 1≤n≤15,∣xi∣,∣yi∣≤200,小数点后最多有 3 位数字。
提示
对于两个点 (x1,y1),(x2,y2),两点之间的距离公式为 (x1−x2)2+(y1−y2)2。
2022.7.13:新增加一组 Hack 数据。
实现代码:
cpp
#include <cstdio>
#include <cstring>
#include <cmath>
#define min(a,b) (((a)<(b))?(a):(b))
double a[20][20];
double x[20],y[20];
double F[18][34000];
int N;
double distance(int v,int w)
{
return sqrt((x[v]-x[w])*(x[v]-x[w])+(y[v]-y[w])*(y[v]-y[w]));
}
int main()
{
int i,j,k;
double ans;
memset(F,127,sizeof(F));
ans=F[0][0];
scanf("%d",&N);
for(i=1;i<=N;i++)
{
scanf("%lf%lf",&x[i],&y[i]);
}
x[0]=0;y[0]=0;
for(i=0;i<=N;i++)
{
for(j=i+1;j<=N;j++)
{
a[i][j]=distance(i,j);
a[j][i]=a[i][j];
}
}
for(i=1;i<=N;i++)
{
F[i][(1<<(i-1))]=a[0][i];
}
for(k=1;k<(1<<N);k++)
{
for(i=1;i<=N;i++)
{
if((k&(1<<(i-1)))==0)
continue;
for(j=1;j<=N;j++)
{
if(i==j)
continue;
if((k&(1<<(j-1)))==0)
continue;
F[i][k]=min(F[i][k],F[j][k-(1<<(i-1))]+a[i][j]);
}
}
}
for(i=1;i<=N;i++)
{
ans=min(ans,F[i][(1<<N)-1]);
}
printf("%.2f\n",ans);
}