2021寒假积分赛(二)补题(1)
E题还有迪杰斯特拉算法的代码没补,后面还有三道题,还是不太会dp,A题是水题,读懂的话还挺好写0.0
一、A - Jolly Jumpers
题目:链接
题意:输入n个数,如果这组数据满足连续元素之间差的绝对值取到1到n-1的所有值的条件,则输出Jolly,否则输出Not jolly。
解题思路
模拟,将数据存入a数组,用数组b存放连续元素之间差的绝对值,然后对b数组排序后再判断。
代码如下:
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
int main()
{
int a[10000],b[10000],n;
int i,j;
while(~scanf("%d", &n)!=EOF){
j=0;
for(i=0;i<n;i++){
cin>>a[i];
if(i>0) b[j++]=abs(a[i]-a[i-1]);
}
sort(b,b+j);
bool flag=true;
for(i=0;i<j;i++){
if(b[i]!=i+1){
flag=false;
break;
}
}
if(flag) cout<<"Jolly"<<endl;
else cout<<"Not jolly"<<endl;
}
return 0;
}
二、C - 取石子游戏
题目:链接
威佐夫博弈(Wythoff’s game): 有两堆各若干个物品,两个人轮流从任一堆取至少一个或同时从两堆中取同样多的物品,规定每次至少取一个,多者不限,最后取光者得胜。详细结论及证明
解题思路
假设两堆石子的初始状态为a,b(a<b)。
设t为t=(int)((b-a)*(1.0+sqrt(5.0))/2.0);
如果t=a则先手败,否则先手胜。
代码如下:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int a,b;
int t;
while(~scanf("%d %d",&a,&b)!=EOF){
if(a>b) swap(a,b);
t=(int)((b-a)*(1.0+sqrt(5.0))/2.0);
if(a==t) cout<<"1"<<endl;
else cout<<"0"<<endl;
}
return 0;
}
三、E - 最短路
题目:链接
解题思路
模板题,可直接套用Floyd模板或Dijkstra模板
代码如下(Floyd):
#include <bits/stdc++.h>
using namespace std;
int M,N;
int road[10000][10000];
void floyd()
{
for(int i=1;i<=N;i++)
{
for(int j=1;j<=N;j++)
{
for(int k=1;k<=N;k++)
road[i][j]=min(road[i][j],road[i][k]+road[k][j]);
}
}
}
int main()
{
while(~scanf("d%,d%",M,N),M||N){
int i,A,B,C;
for(i=0;i<M;i++){
cin>>A>>B>>C;
road[A][B]=road[B][A]=C;
}
floyd();
cout<<road[1][N]<<endl;
}
return 0;
}
四、F - 寒冰王座
题目:链接
解题思路
两种方法:一种是替换,将350看成200+150,将200看成150+50,最后只要看在花n个150的时候还能再花多少个50;
本题为完全背包问题,所以另一种方法是套用完全背包模板。
方法一
代码如下:
#include <iostream>
using namespace std;
//350可以看作200+150,200可以看作150+50。
int main()
{
int T;
cin>>T;
int i;
for(i=0;i<T;i++){
int N,sum,n; //带的钱最多买n个150的商品
cin>>N;
sum=N;
n=sum/150;
sum%=150;
if(sum/50<=n){
sum%=50;
}
else{
sum=sum-50*n;
}
cout<<sum<<endl;
}
return 0;
}
方法二
代码如下:
#include <iostream>
using namespace std;
//完全背包
int price[3]={150,200,350};
int dp[10000];
int main(){
int T;
cin>>T;
int i;
while(T--){
int N;
cin>>N;
for(int i = 0; i < 3; i++){
for(int j = price[i]; j <= N; j++){
dp[j] = max(dp[j], dp[j-price[i]]+price[i]);
}
}
cout<<N-dp[N]<<endl;
}
return 0;
}