题意: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 ",r-l+1); else printf("0 "); }
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; }