題目總結1

There are n cities and n - 1 roads in the Seven Kingdoms, each road connects two cities and we can reach any city from any other by the roads.

Theon and Yara Greyjoy are on a horse in the first city, they are starting traveling through the roads. But the weather is foggy, so they can’t see where the horse brings them. When the horse reaches a city (including the first one), it goes to one of the cities connected to the current city. But it is a strange horse, it only goes to cities in which they weren’t before. In each such city, the horse goes with equal probabilities and it stops when there are no such cities.

Let the length of each road be 1. The journey starts in the city 1. What is the expected length (expected value of length) of their journey? You can read about expected (average) value by the link https://en.wikipedia.org/wiki/Expected_value.

Input
The first line contains a single integer n (1 ≤ n ≤ 100000) — number of cities.

Then n - 1 lines follow. The i-th line of these lines contains two integers ui and vi (1 ≤ ui, vi ≤ n, ui ≠ vi) — the cities connected by the i-th road.

It is guaranteed that one can reach any city from any other by the roads.

Output
Print a number — the expected length of their journey. The journey starts in the city 1.

Your answer will be considered correct if its absolute or relative error does not exceed 10 - 6.

Namely: let’s assume that your answer is a, and the answer of the jury is b. The checker program will consider your answer correct, if .

Examples
Input
4
1 2
1 3
2 4
Output
1.500000000000000
Input
5
1 2
1 3
3 4
2 5
Output
2.000000000000000
暴力搜索
n點n-1邊不成環,由一點開始分叉。搜索較容易想

#include<iostream>
#include<cstdio>
using namespace std;
int n;
bool vis[100001]={0};
int cnt[100001];
double ans=0;
int sum;
int k=0;
struct p
{
    int a,b;
};
p m[100001];
int f[100001]={0};
void search(int v)
{
    //if(f[v]) sum=f[v];
    //else if(cnt[v]>1){sum=sum*cnt[v];f[v]=sum;}
    if(cnt[v]==0) {ans=ans+double(k)/(sum*1.0); return;}
    if(f[v]!=0) sum=f[v];
    else if(cnt[v]>1) {sum=sum*cnt[v];f[v]=sum;}
    for(int i=1;i<n;i++)
    {
        //if(f[v]) sum=f[v];
        //else if(cnt[v]>1) sum=sum*cnt[v];
        if(m[i].a==v||m[i].b==v)
           if(vis[i]==0)
        {
            vis[i]=1;
            k++;
           // if(f[v]!=0) sum=f[v];
           // else if(cnt[v]>1){ sum=sum*cnt[v]; f[v]=sum;}
            if(v==m[i].a){ search(m[i].b);}
            else {  search(m[i].a);}
            k--;
            //if(i==n-1&&cnt[v]>1) sum=sum/cnt[v];
           vis[i]=0;
        }
        if(i==n-1&&cnt[v]>1) sum=sum/cnt[v];
    }
}
int main()
{
   cin>>n;
   int c,d;
   if(n==1) {cout<<'0'<<endl; return 0;}
   for(int i=1;i<n;i++)
   {
      cin>>c>>d;
      m[i].a=c;
      m[i].b=d;
      cnt[c]++;
      cnt[d]++;
   }
   for(int i=2;i<=n;i++)
   {
       cnt[i]=cnt[i]-1;
   }
   /*for(int i=1;i<=n;i++)
   {
       cout<<cnt[i]<<endl;
   }*/
 //  cout<<endl;
   sum=1;
   search(1);
   printf("%.15lf\n",ans);
}

弊端每次都全搜,浪費,可以用vector二維數組,減少搜索次數

#include <iostream>
#include<vector>
#include<cstdio>
#include<algorithm>
using namespace std;
vector<int> tree[100001];
bool vis[100001];
int n;
double ans=0;
void dfs(int v,double sum,int step)
{
    if(tree[v].size()==1&&v!=1)
    {
        ans=ans+step*sum;
        return ;
    }
       int len=tree[v].size();
       for(int i=0;i<len;i++)
       {
           int ti=tree[v][i];
           if(vis[ti]==0)
           {
               vis[ti]=1;
               if(v==1){dfs(ti,sum/len,step+1);}
               else {dfs(ti,sum/(len-1), step+1);}
           }
       }
}
int main()
{
    scanf("%d",&n);
    int a,b;
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&a,&b);
        tree[a].push_back(b);
        tree[b].push_back(a);
    }
    vis[1]=1;
    dfs(1,1,0);
    printf("%.15lf\n",ans);
    return 0;
}

好處很明顯,搜索次數大大減少
有一個注意點最好不要用路徑長度除以最終分叉的乘積,若分母過大啊,電腦懵逼,把他搞成0;
與之相似的一道題
You are given two strings s and t consisting of lowercase Latin letters. Also you have a string z which is initially empty. You want string z to be equal to string t. You can perform the following operation to achieve this: append any subsequence of s at the end of string z. A subsequence is a sequence that can be derived from the given sequence by deleting zero or more elements without changing the order of the remaining elements. For example, if z=ac, s=abcde, you may turn z into following strings in one operation:

z=acace (if we choose subsequence ace);
z=acbcd (if we choose subsequence bcd);
z=acbce (if we choose subsequence bce).
Note that after this operation string s doesn’t change.

Calculate the minimum number of such operations to turn string z into string t.

Input
The first line contains the integer T (1≤T≤100) — the number of test cases.

The first line of each testcase contains one string s (1≤|s|≤105) consisting of lowercase Latin letters.

The second line of each testcase contains one string t (1≤|t|≤105) consisting of lowercase Latin letters.

It is guaranteed that the total length of all strings s and t in the input does not exceed 2⋅105.

Output
For each testcase, print one integer — the minimum number of operations to turn string z into string t. If it’s impossible print −1.

Example
Input
3
aabce
ace
abacaba
aax
ty
yyt
Output
1
-1
3
暴力搜索很好想但浪費時間,所以可以和上一道題進行同樣的處理,用動態二維數組來存儲每一個字母的出現的書序。然後查找。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
char s[100001],t[100001];
int main()
{
    int n;
    cin>>n;
    while(n--){
        scanf("%s%s",s,t);
        vector<int>p[30];
        for(int i=0;s[i];i++)
            p[s[i]-'a'].push_back(i);
        int ans=1,flag=1;
        int pos,ppos=-1;
        for(int i=0;t[i];i++)
            {
            int k=t[i]-'a';
            if(p[k].size()==0)
                {
                flag=0;
                break;
                }
            pos=upper_bound(p[k].begin(),p[k].end(),ppos)-p[k].begin();
            if(pos==p[k].size())
                {
                ans++;
                pos=0;
                }
            ppos=p[k][pos];
           }
        if(!flag) cout<<"-1"<<endl;
        else cout<<ans<<endl;
    }
    return 0;
}

bound是一個比較好用的功能,
lower_bound( )和upper_bound( )都是在排好序的數組中使用的。

他們利用二分查找,以O(logn)的時間複雜度返回一個符合條件的索引值。下面進行解析:

非重載的lower_bound( )和upper_bound( )用於在從小到大的排序數組中的查找:

lower_bound( begin,end,num):從數組的begin位置到end-1位置二分查找第一個大於或等於num的數字,找到返回該數字的地址,不存在則返回end。通過返回的地址減去起始地址begin,得到找到數字在數組中的下標。

upper_bound( begin,end,num):從數組的begin位置到end-1位置二分查找第一個大於num的數字,找到返回該數字的地址,不存在則返回end。通過返回的地址減去起始地址begin,得到找到數字在數組中的下標。

在從大到小的排序數組中,通過greater重載lower_bound()和upper_bound(),比如int數組就是greater:

lower_bound( begin,end,num,greater() ): 從數組的begin位置到end-1位置二分查找第一個小於或等於num的數字,找到返回該數字的地址,不存在則返回end。通過返回的地址減去起始地址begin,得到找到數字在數組中的下標。

upper_bound( begin,end,num,greater() ):從數組的begin位置到end-1位置二分查找第一個小於num的數字,找到返回該數字的地址,不存在則返回end。通過返回的地址減去起始地址begin,得到找到數字在數組中的下標。
————————————————
版權聲明:本文爲CSDN博主「Wzning0421」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/hanzhen7541/article/details/99722948

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章