Drink
Problem Description
我们有 n 种不同的饮料,每种饮料有无限多瓶,第 i 种饮料一瓶提供 x[i] 毫升的水分,包含 y[i] 卡路里。
现在我们需要选择一种饮料一直喝,直到补充了至少 m 毫升的水分,我们想使得摄入的卡路里总和最小。请求出这个最小值。
一旦打开一瓶饮料,就一定要喝完。
Input
第一行一个整数 test(1≤test≤100) 表示数据组数。
对于每组数据,第一行两个整数 n,m(1≤n≤100,1≤m≤10000)。
接下来 n 行,每行两个整数 x[i],y[i](1≤x[i],y[i]≤100)。
Output
对于每组数据,一行一个整数表示答案。
Sample Input
2
1 10
3 3
2 10
3 3
2 1
Sample Output
12
5
思路:
求出每次需要补充的瓶数,进一步求出这次最少补充卡路里数多少,用min求出最小值
代码:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
int main()
{
ios::sync_with_stdio(false);//关闭同步
cout.tie(NULL);
cin.tie(NULL);
int t,n,m,x,y,mi=10086;
cin>>t;
while(t--){
cin>>n>>m;
while(n--)
{
cin>>x>>y;
int k=m/x;//补充完水分需要多少水
if(m-x*k)k++;//如果 x没有整除,数量增加
y=k*y;//卡路里数量
mi=min(y,mi);
}
cout<<mi<<endl;
mi=10086; //更新数量
}
return 0;
}
GPA
Problem Description
小沃沃一共参加了 4 门考试,每门考试满分 100 分,最低 0 分,分数是整数。
给定四门考试的总分,请问在最优情况下,四门课绩点的和最高是多少?
分数与绩点之间的对应关系如下:
95~100 4.3
90~94 4.0
85~89 3.7
80~84 3.3
75~79 3.0
70~74 2.7
67~69 2.3
65~66 2.0
62~64 1.7
60~61 1.0
0~59 0
Input
第一行一个正整数 test(1≤test≤401) 表示数据组数。
接下来 test 行,每行一个正整数 x 表示四门考试的总分 (0≤x≤400)。
Output
对于每组数据,一行一个数表示答案。答案保留一位小数。
Sample Input
2
0
400
Sample Output
0.0
17.2
思路:
因为是用分数段,所以直接算每个分数段加起来和n比较,然后如果这次比较比n小,就对比上一次的学分绩谁高,更新一下
代码:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
int a[]={0,60,62,65,67,70,75,80,85,90,95};//初始化分数段
double b[305];
void init()//初始化分数段的学分绩
{
b[0]=0.0;
b[60]=1.0;
b[62]=1.7;
b[65]=2.0;
b[67]=2.3;
b[70]=2.7;
b[75]=3.0;
b[80]=3.3;
b[85]=3.7;
b[90]=4.0;
b[95]=4.3;
}
int main()
{
init();
ios::sync_with_stdio(false);//关闭同步
cout.tie(NULL);
cin.tie(NULL);
int t;
cin>>t;
while(t--){
int n;
cin>>n;
double ans=0.0;
for(int i=0;i<=10;i++)
{
for(int j=0;j<=10;j++)
{
for(int k=0;k<=10;k++)
{
for(int o=0;o<=10;o++)
{
if(a[i]+a[j]+a[k]+a[o]<=n)
{
ans=max(ans,b[a[i]]+b[a[j]]+b[a[k]]+b[a[o]]);//四个循环,如果他们每个分数小于n,就把他们的学分绩算一遍,取最大值
}
}
}
}
}
printf("%.1f\n",ans);
}
return 0;
}
DEC
Problem Description
初始有 a,b 两个正整数,每次可以从中选一个大于 1 的数减 1,最后两个都会减到 1,我们想知道在过程中两个数互质的次数最多是多少。
Input
第一行一个正整数 test(1≤test≤1000000) 表示数据组数。
接下来 test 行,每行两个正整数 a,b(1≤a,b≤1000)。
Output
对于每组数据,一行一个整数表示答案。
Sample Input
1
2 3
Sample Output
4
样例解释
2 3 -> 1 3 -> 1 2 -> 1 1
思路:
初始化dp,o1查询
代码:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn = 1e3 + 7;
int dp[1005][1005];
inline int gcd(int x,int y) {//gcd函数
return y == 0 ? x : gcd(y,x % y);
}
int main()
{
dp[1][1]=1;
for(int i=1;i<=1000;i++)//dp初始化
{
for(int j=1;j<=1000;j++)
{
if(dp[i][j])continue;
dp[i][j]=max(dp[i-1][j]+(gcd(i,j)==1?1:0),dp[i][j-1]+(gcd(i,j)==1?1:0));
}
}
int T;scanf("%d",&T);//o1询问
while(T--) {
int a,b;scanf("%d%d",&a,&b);
printf("%d\n",dp[a][b]);
}
return 0;
}
Civilization
Problem Description
这是一个回合制游戏,每一回合开始前会进行上一回合的结算。
有一张 n∗n 的棋盘,我们出生在一个初始位置 (x,y),现在我们要选择一个位置建设城市。
你的人物每回合可以移动到距离你曼哈顿距离不超过 2 的位置,移动完成后可以选择是否建立城市。
建立城市后,你的人物消失,成为一个人口为 1 的城市,这个人口要下回合才可以工作。如果不移动,直接在 (x,y) 建城,第 1 回合就可以开始工作。
对于城市的每个居民,你可以安排他到距离城市曼哈顿距离小于等于 3 的位置进行工作,此居民可以瞬间到达该位置,每个位置最多安排一个居民,失业的人口不会生产任何食物。
注意,城市位置上必须有一个居民在工作。
结算按照如下顺序:
1. 如果位置 (i,j) 上有一个工作居民,则获得 a[i][j] 的食物。
2. 如果当前城市人口为 i,且食物达到 8∗i2 时,你获得一个新的居民,下一回合可以进行操作。
当结算后城市总人口达到 9 游戏结束。
初始食物数量为 0,人口上涨不会导致之前积累的食物消失。输出最少几个回合能让游戏结束。
Input
第一行一个正整数 test(1≤test≤10) 表示数据组数。
对于每组数据,第一行三个正整数 n(2≤n≤500),x(1≤x≤n),y(1≤y≤n),分别表示棋盘大小和起始位置。
接下来 n 行,每行 n 个整数,第 i 行第 j 列的整数表示 a[i][j](1≤a[i][j]≤3)。
Output
对于每组数据,一行一个整数表示答案。
Sample Input
1
10 9 8
1 2 2 1 2 3 1 1 2 1
2 1 3 3 3 2 3 2 3 1
1 1 3 1 1 3 2 2 1 2
3 1 3 1 3 3 1 3 1 3
3 2 3 1 3 1 2 2 2 1
2 3 2 3 2 2 3 1 2 3
3 1 3 3 2 2 3 2 3 3
1 3 3 2 3 2 2 2 1 1
3 3 1 2 3 2 1 2 1 2
1 1 3 1 3 1 1 1 3 3
Sample Output
39
思路:
直接模拟
代码:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn=1e3+7;
int a[maxn][maxn],d[maxn][maxn];
int n;
int getdis(pair<int,int>a,pair<int,int>b)//计算曼哈顿距离
{
return abs(a.first-b.first)+abs(a.second-b.second);
}
int get(int x,int y) { //建城市的位置
int t1 = 0,t2 = 0,t3 = 0;
for(int i = max(1,x - 3);i <= min(n,x + 3);i++) {
for(int j = max(1,y - 3);j <= min(n,y + 3);j++) {
if(i == x && j == y) continue;
if(getdis({x,y},{i,j}) <= 3) {
int num = a[i][j];
if(num == 1) t1++;
if(num == 2) t2++;
if(num == 3) t3++;
}
}
}
int sum = a[x][y]; //每一回合可以得到的食物
int sumall = 0; //已经获得的食物
int ans = 0;
int person = 1; //城市人数
while(person < 9) { //当前回合
int nex = 8 * person * person;
int num = (nex - sumall) / sum; //要多少回合才能加人
if((nex - sumall) % sum) num++;
sumall += num * sum;
ans += num;
person++;
if(t3) {
sum += 3;
t3--;
} else if(t2) {
sum += 2;
t2--;
} else if(t1) {
sum += 1;
t1--;
}
}
return ans;
}
int main() {
int T;scanf("%d",&T);
while(T--) {
int x,y;scanf("%d%d%d",&n,&x,&y);
for(int i = 1;i <= n;i++) {
for(int j = 1;j <= n;j++) {
scanf("%d",&a[i][j]);
}
}
int ans = get(x,y);
for(int i = 1;i <= n;i++) {
for(int j = 1;j <= n;j++) {
if(i == x && j == y) continue;
int num = getdis({x,y},{i,j});
if(num % 2) {
num = num / 2 + 1;
} else num = num / 2;
ans = min(ans,get(i,j) + num);
}
}
printf("%d\n",ans);
}
return 0;
}