GCPC 2018

 

C、Coolest Ski Route

题意:n个点,m条边组成的有向图,求任意两点之间的最长路径

dfs记忆化搜索

#include<iostream>
#include<string.h>
#include<string>
#include<algorithm>
#include<math.h>
#include<string>
#include<string.h>
#include<vector>
#include<utility>
#include<map>
#include<queue>
#include<set>
#define mx 0x3f3f3f3f
#define ll long long
using namespace std;
int dis[1005],way[1005][1005],vis[1005],flag[1005];
int n,m;
int dfs(int x)
{
    if(vis[x]==1)
        return dis[x];
    for(int i=1;i<=n;i++)
    {
        if(way[x][i]!=0)
            dis[x]=max(dis[x],dfs(i)+way[x][i]);//dis[x]表示以x为起点能走的最长路径是dis[x]
    }
    vis[x]=1;
    return dis[x];
}
int main()
{
    cin>>n>>m;
    for(int i=0;i<m;i++)
    {
        int x,y,z;
        cin>>x>>y>>z;
        flag[y]=1;//标记终点
        if(way[x][y]!=0)
            way[x][y]=max(way[x][y],z);
        else
            way[x][y]=z;
    }
    int ans=0;
    for(int i=1;i<=n;i++)//枚举搜索起点
    {
        if(flag[i]==0)//给的是有向图,只能从有向图的起点开始搜索
            ans=max(ans,dfs(i));
    }
    cout<<ans<<endl;
    return 0;
}
/*
5 5
1 2 15
2 3 12
1 4 17
4 2 11
5 4 9

6 6
1 2 2
4 5 2
2 3 3
1 3 2
5 6 2
1 2 4
*/

 

 

Gym - 102021D:Down the Pyramid

题意:给你一层数,让你求出它下面的一层数,上面的每一个数都是下层相邻两个数的和。(就像图中的数字金字塔一样)。问你下面一层有多少种满足的方案。

思路:假设给出的值为,a1,a2,a3,a3...,假设下面的第一个数b0=x,那么可以推得第二个数b1=a1-x,第三个数就是a2-(a1-x),以此类推。其中bo...bn要满足的条件就是每一项都大于等于零。所以就可推得关于x 的不等式,所以就可以求出x的一个最小的范围,所以就可求出方案数。

列出不等式,解x的范围

b1=a1-x>=0                       x<=a1   

b2=a2-(a1-x)>=0,              x>=a1-a2

b3=a3-(a2-(a1-x))>=0       x<=a1-a2+a3

b4=a4-a3+a2-a1+x>=0     x>=a1-a2+a3-a4

 

奇数项<=的解取x得最小解

偶数项>=得解取x得最大解

 

#include<iostream>
#include<string.h>
#include<string>
#include<algorithm>
#include<math.h>
#include<string>
#include<string.h>
#include<vector>
#include<utility>
#include<map>
#include<queue>
#include<set>
#define mx 0x3f3f3f3f
#define ll long long
using namespace std;
int n;
int a[1000005];
int main()
{
    int cnt=0,num;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    int l=0,r=mx,ans=0;
    for(int i=1;i<=n;i++)
    {
        ans=a[i]-ans;
        if(i%2==1)
            r=min(r,ans);
        else
            l=max(l,-ans);
    }
    if(r>=l)
        printf("%d\n",r-l+1);
    else
        printf("0\n");
}

 

 

 

 

 Gym - 102021E :Expired License

题意:给你一对浮点数,让你判断这对浮点数的比值能否用一对素数的比值所表示,如果可以就输出两个素数。

分析:首先将所给数转化成字符串处理(double转化成int数据会变化),两个数统一先乘以10^6化成整数,然后两数在除以他们的最大公因子判断是否为素数。其中里面包含一种特殊情况,就是当两数相等时,直接输出2,2

 

#include<iostream>
#include<string.h>
#include<string>
#include<algorithm>
#include<math.h>
#include<string>
#include<string.h>
#include<vector>
#include<utility>
#include<map>
#include<queue>
#include<set>
#define mx 0x3f3f3f3f
#define ll long long
using namespace std;
const int maxn = 1e7 + 10;
int prim[maxn], w[maxn], cnt = 0;//prim[i]起标记作用,prim[i]==0表示i是质数
int x[maxn];//x[i]表示偶数是i的符合条件的两个质数是x[i]和i-x[i];
void init()
{
    memset(prim, 0, sizeof(prim));
    for (int i = 2; i < maxn; i++)
    {
        if (prim[i]) //判断i是否为偶数
            continue;
        w[cnt++] = i;//w存质数
        for (int j = i << 1; j < maxn; j += i)//把所有质数的倍数标记
            prim[j] = 1;
    }

}
ll gcd(ll a, ll b)//最大公约数
{
    return b == 0 ? a : gcd(b, a % b);
}
string s1,s2;
int main()
{
    int t;
    cin>>t;
    init();
    prim[1]=1;
    while(t--)
    {
        ll k1=0,k2=0,pos1=6,pos2=6;//先默认乘以10^6
        cin>>s1>>s2;
        int len1=s1.length();
        int len2=s2.length();
        for(int i=0;s1[i];i++)
        {
            if(s1[i]!='.')
                k1=k1*10+(s1[i]-'0');
            else
                pos1=len1-i-1;
        }
        for(int i=0;s2[i];i++)
        {
            if(s2[i]!='.')
                k2=k2*10+(s2[i]-'0');
            else
                pos2=len2-i-1;
        }
        while(pos1)
        {
            k1=k1*10;
            pos1--;
        }
        while(pos2)
        {
            k2=k2*10;
            pos2--;
        }
        if(k1==k2)
        {
            cout<<2<<' '<<2<<endl;
            continue;
        }
        ll temp=gcd(k1,k2);
        k1=k1/temp;
        k2=k2/temp;
    
        if(prim[k1]==0&&prim[k2]==0)
            cout<<k1<<' '<<k2<<endl;
        else
            cout<<"impossible"<<endl;
    }
    return 0;
}

 

 

Gym - 102021F :Fighting Monsters

题意:给定N个怪兽,问能否选出两个怪兽,使得他们相互攻击,最后活着的怪兽剩1滴血,死的怪兽的血为零或者为负数。

题解:找规律,看在给定的n个数中,是否存在一组相邻的斐波那契数

 

#include<iostream>
#include<string.h>
#include<string>
#include<algorithm>
#include<math.h>
#include<string>
#include<string.h>
#include<vector>
#include<utility>
#include<map>
#include<queue>
#include<set>
#define mx 0x3f3f3f3f
#define ll long long
using namespace std;
ll f[10000005],vis[1000006];//vis标记这个斐波那契数是否在n个数里面
map<ll,ll>m;//标记是否是斐波那契数
struct node
{
    int x;
    int pos;
}p[200005];
bool cmp(node a,node b)
{
    return a.x<b.x;
}
void feibo()
{
    f[0]=0;
    f[1]=1,f[2]=2;
    m[1]=1,m[2]=2;
    for(int i=3;i<=10006;i++)
    {
        f[i]=f[i-1]+f[i-2];
        m[f[i]]=i;
        if(f[i]>=10000006)
            break;
    }
}
int main()
{
    int n;
    feibo();
    // for(int i=0;f[i];i++)
    //     cout<<f[i]<<endl;
    scanf("%d",&n);
    int k=0;
    for(int i=1;i<=n;i++)
    {
        int temp;
        scanf("%d",&temp);
        if(vis[temp]!=0&&temp!=1)//要把重复得数去掉,斐波那契数是除1以外是没有重复的
            continue;
        vis[temp]=i;
        p[k].x=temp;
        p[k].pos=i;
        k++;
    }
    sort(p,p+k,cmp);
    int flag=0;
    for(int i=0;i<k;i++)
    {
        if(m[p[i].x]!=0)
        {
            int pos=m[p[i].x];
            if(p[i].x==p[i+1].x)
            {
                cout<<p[i].pos<<' '<<p[i+1].pos<<endl;
                flag=1;
                break;
            }
            else if(vis[f[pos-1]])
            {
                cout<<p[i].pos<<' '<<vis[f[pos-1]]<<endl;
                flag=1;
                break;
            }
            else if(vis[f[pos+1]])
            {
                cout<<p[i].pos<<' '<<vis[f[pos+1]]<<endl;
                flag=1;
                break;
            }
        }
    }
    if(flag==0)
        cout<<"impossible"<<endl;
    return 0;   
}

 

转载于:https://www.cnblogs.com/-citywall123/p/11360672.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值