1. 程式人生 > >【計算幾何】【DP】【tarjan】Day 10.6

【計算幾何】【DP】【tarjan】Day 10.6

long long pri cout logs 前綴 ret ble freopen style

T1 計算幾何+遞推

 1 #include <cstdio>
 2 #include <cmath>
 3 double w,x,r;
 4 int p;
 5 int main()
 6 {
 7     freopen("coin.in","r",stdin);
 8     freopen("coin.out","w",stdout);
 9     scanf("%lf%d",&r,&p);
10     w=r*sqrt(3.0)/3;
11     x=w*2-r;
12     w-=x;
13     for (int i=2;i<=p;i++)
14 { 15 x=pow(w,2.0)/(2*(w+r)); 16 w-=2*x; 17 } 18 printf("%.6lf",x); 19 }

T2 數位DP

轉移動作:選接下來的數

那麽如何依據轉移動作建立轉移方程?,考慮:每一位的數受上一位所選擇的數所影響,所以定義狀態的時候需要考慮到這點

定義f[i][j]位已經選擇了前i位且第i位選擇了j且已選擇的前綴小於原數對應的前綴

想一想:為什麽不定義f[i][j]位已經選擇了前i位且第i位選擇了j且已選擇的前綴小於等於原數對應的前綴

 1 #include <cstdio>
 2
#include <iostream> 3 #include <cstring> 4 #include <cmath> 5 #define ll long long 6 using namespace std; 7 ll l,r,f[19][10],w[19],ans=0,ten[19]={1}; 8 ll count(ll x) 9 { 10 ll s=0; 11 while(x) 12 { 13 s++; 14 w[s]=x%10; 15 x/=10; 16 } 17 return
s; 18 } 19 ll check(ll x)//統計小於等於x且和x位數相同的幸運數數量 20 { 21 memset(f,0,sizeof(f)); 22 ll cnt=count(x),s=0,pd=1; 23 if (cnt==0) return 0; 24 for (int i=1;i<w[cnt];i++) f[cnt][i]=1; 25 for (int i=cnt-1;i>=1;i--)//統計小於x且和x位數相同的幸運數數量 26 { 27 for (int j=0;j<=9;j++) 28 { 29 for (int k=0;k<=9;k++) 30 { 31 if (abs(j-k)>=2) 32 { 33 if (k==w[i+1]&&j<w[i]) f[i][j]+=pd;//從前綴完全相同的狀態轉移(前提是第i+1位及之前的前綴合法) 34 f[i][j]+=f[i+1][k]; 35 } 36 } 37 } 38 if (abs(w[i]-w[i+1])<2) pd=0;//判定第i位及之前的前綴合法 39 } 40 //統計比x小的幸運數 41 for (int i=0;i<=9;i++) s+=f[1][i]; 42 //統計x本身是不是幸運數 43 s+=pd; 44 return s; 45 } 46 int main() 47 { 48 freopen("lucky.in","r",stdin); 49 freopen("lucky.out","w",stdout); 50 cin>>l>>r; 51 for (int i=1;i<=17;i++) ten[i]=ten[i-1]*10; 52 for (int i=count(l);i<=count(r)-1;i++) ans+=check(ten[i]-1); 53 ans+=check(r)-check(l-1); 54 cout<<ans<<endl; 55 }

【計算幾何】【DP】【tarjan】Day 10.6