貪心-國王的遊戲(大數乘除)、連線子串
目錄
程式碼:
國王的遊戲:
題目:
恰逢 H 國國慶,國王邀請 n 位大臣來玩一個有獎遊戲。首先,他讓每個大臣在左、右手上面分別寫下一個整數,國王自己也在左、右手上各寫一個整數。然後,讓這 n 位大臣排成一排,國王站在隊伍的最前面。排好隊後,所有的大臣都會獲得國王獎賞的若干金幣,每位大臣獲得的金幣數分別是:排在該大臣前面的所有人的左手上的數的乘積除以他自己右手上的數,然後向下取整得到的結果。
國王不希望某一個大臣獲得特別多的獎賞,所以他想請你幫他重新安排一下隊伍的順序,使得獲得獎賞最多的大臣,所獲獎賞儘可能的少。注意,國王的位置始終在隊伍的最前面。
對於 20%的資料,有 1≤ n≤ 10,0 < a,b < 8 ;
對於 40%的資料,有 1≤ n≤20,0 <a,b<8 ;
對於 60%的資料,有 1≤ n≤100 ;
對於 60%的資料,保證答案不超過 109 ;
對於 100%的資料,有 1 ≤ n ≤1,000,0 < a,b < 10000 。
思路:
儘可能少,確定貪心策略,發現兩個大臣互換位置對其它大臣獲得獎賞數量沒有影響,比較下換位置前和換位置後哪一個最大的較小。
前k個大臣左手乘積為L,第k+1個大臣L1,R1,第k+2個大臣L2,R2;假設讓第k+1個大臣在前面更適合,當他在前時,最大值為max(L/R1①,L*L1/R2②),當他在後面時,最大值為max(L/R2③,L*L2/R1④);讓他在前面更合適,那麼就要保證前者的max小於後者的max,顯然①<④,③<②,那麼後者肯定要選擇④(如果選②必定比前者小,因為他小於③)。這樣只要能保證②<④即可,化簡得L1*R1<L2*R2。由此可得,對於任意兩個大臣,左右手數相乘小的靠前獲得的最大值最小。
資料範圍感人,10000個大臣,每個大人最多10000,那就是10000^10000。接下來看下高精度大數乘除:
陣列儲存大資料乘法,可以理解為把每一位拆分為(xn*10^n……..x1*10+x0*1)*x對每一位乘,一旦係數大於10,就可以進位了,注意的是,每一位都要僅為,因為每一位數都可能大於9。所以至少迴圈len次。
大資料高精度乘除模板:
乘:
void mul(ll x){
for(int i = 1;i <= len;i++)
num[i] = num[i]*x;
int cnt = 1;
while(num[cnt] > 9||cnt <= len){//個位無進位不代表其他位無進位
num[cnt+1] += num[cnt]/10;
num[cnt]%=10;
cnt++;
}
len=cnt;
if(!num[len]) len--;
return ;
}
除:模擬除法過程
void div(ll x){
for(int i = len;i >= 1;i--){
num[i-1] += (num[i]%x)*10;
num[i]/=x;
}
while(!num[len]) len--;
}
程式碼:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cstdlib>
#include<map>
#include<cmath>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn = 1e5+50;
typedef struct{
ll l;
ll r;
ll z;
}hand;
hand arr[maxn];
int len,n;
ll num[maxn];//最多1e5個1e4相乘 也就是4e5+1位數
bool cmp(hand a,hand b){
return a.z < b.z;//奇葩 等號竟然沒過。
}
void mul(ll x){
for(int i = 1;i <= len;i++)
num[i] = num[i]*x;
int cnt = 1;
while(num[cnt] > 9||cnt <= len){//個位無進位不代表其他位無進位
num[cnt+1] += num[cnt]/10;
num[cnt]%=10;
cnt++;
}
len=cnt;
if(!num[len]) len--;
return ;
}
void div(ll x){
for(int i = len;i >= 1;i--){
num[i-1] += (num[i]%x)*10;
num[i]/=x;
}
while(!num[len]) len--;
}
int main(){
cin >> n;
cin >> arr[0].l >> arr[0].r;
for(int i = 1;i <= n;i++){
cin >> arr[i].l >> arr[i].r;
arr[i].z = arr[i].l*arr[i].r;
}
sort(arr+1,arr+1+n,cmp);
len=1;num[1]=1;
for(int i = 0;i<n;i++) mul(arr[i].l);
div(arr[n].r);
for(int i = len;i >= 1;i--) cout<<num[i];
if (!len) printf("1");
return 0;
}
連線子串
題目:
設有n個正整數(n ≤ 20),將它們聯接成一排,組成一個最大的多位整數。
例如:n=3時,3個整數13,312,343聯接成的最大整數為:34331213
又如:n=4時,4個整數7,13,4,246聯接成的最大整數為:7424613
輸入描述:
第一行,一個正整數n。
第二行,n個正整數。
輸出描述:
一個正整數,表示最大的整數
思路:
不可以直接判斷字典序:23 2323231 or 33 331 9錯誤,如果想著判斷這些特例就會很麻煩。
同樣,任何相鄰的兩個子串交換不會影響其它子串的貢獻,就看一下互換前後哪一種最大。
現在感覺在冒泡。最後只要能達到任何兩個相鄰子串互換都不如不換,就是最大字典序了。
假設對子串s1…sm…sn….. 如果sm和sn交換更好的話,sm+1在sn前面又更好些,sm+2在sn前面又更好些(因為之前肯定比較過了在sn前面更好)……最後又回到了原來的位置。
冒泡複雜度太高,冒泡就是排序,不如直接快排,sort函式cmp一下就可以了。
bool cmp(string a,string b){
return a+b>b+a;
}
程式碼:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cstdlib>
#include<map>
#include<cmath>
#include<vector>
//思路:....AB...若想讓序列最大 保證每一對相鄰的A+B>B+A即可,轉化為排序。
//不可以直接判斷字典序:23 2323231 or 33 331 9錯誤
using namespace std;
typedef long long ll;
const int maxn = 1e6+50;
string s[30];
string ans;
bool cmp(string a,string b){
return a+b>b+a;
}
int main(){
int n;
cin >> n;
for(int i = 0;i < n;i++) cin>>s[i];
sort(s,s+n,cmp);
for(int i = 0;i < n;i++) ans+=s[i];
cout << ans;
return 0;
}
相關文章
- HDU 4550卡片遊戲(貪心)遊戲
- [zt] JDBC連線Oracle RAC的連線串配置JDBCOracle
- 貪心
- 變數子串的常用操作變數
- 資料庫的連線串資料庫
- 反悔貪心
- Supermarket(貪心)
- Python連線兩個字串並去除首尾重複子串Python字串
- 線性dp:最長公共子串
- oracle連線串的一種寫法Oracle
- 經典回合策略遊戲《國王的恩賜2》今日正式上線!遊戲
- 貪心——55. 跳躍遊戲 && 45.跳躍遊戲II遊戲
- P1080 國王遊戲遊戲
- 貪心模式記錄模式
- 貪心、構造合集
- 貪心演算法演算法
- 反悔貪心雜題
- LeetCode 55. 跳躍遊戲 ( 回溯 dp 貪心LeetCode遊戲
- Oracle 11gR2 RAC的JDBC連線串OracleJDBC
- 《科學報告》:研究顯示電子遊戲似乎會改變大腦的連線方式遊戲
- 子串位置
- 一種型別的樹貪心型別
- Least Cost Bracket Sequence(貪心)ASTRacket
- 牛客 tokitsukaze and Soldier 貪心
- 24/03/20 貪心(一)
- 7.5 - 貪心篇完結
- 貪心 做題筆記筆記
- 「貪心」做題記錄
- leetcode:跳躍遊戲II(java貪心演算法)LeetCode遊戲Java演算法
- 【LISTENER】資料庫連線串的幾種寫法資料庫
- 第51條:當心字串連線的效能字串
- Java 的字串和子串Java字串
- PostgreSQL連線串URI配置(libpq相容配置)SQL
- 學一下貪心演算法-學一下貪心演算法演算法
- 子串查詢
- 查詢子串
- 最長子串
- 貪心演算法(貪婪演算法,greedy algorithm)演算法Go