題目描述
這裡$b$表示該格仔放的物件黑色面朝上、$w$表示該格仔放的物件白色朝上。如果我們選擇翻轉第三行的第乙個物件,那麼格仔狀態將變為:
bwbw
bwww
wwwb
wwwb
遊戲的目標是翻轉到所有的物件白色朝上或黑色朝上。你的任務就是寫乙個程式來求最少的翻轉次數來實現這一目標。
輸入格式
輸入檔案包含$4$行,每行$4$個字元,每個字元$w$或$b$表示遊戲開始時格仔上物件的狀態。
輸出格式
輸出檔案僅乙個整數,即從給定狀態到實現這一任務的最少翻轉次數。如果給定的狀態就已經實現了目標就輸出$0$
,如果不可能實現目標就輸出:$impossible$。
樣例
樣例輸入
bwwb
bbwb
bwwb
bwww
樣例輸出
4
#include using namespace std;
const int inf=0x3f3f3f3f;
int ans,cnt;
char s[5][5],tmp[5][5];
void flip(char &ch)
void press(int i,int j)
void calc(int x,char ch)
}for(int i=2;i<=4;i++) }}
for(int i=1;i<=4;i++)
ans=min(ans,cnt);
}int main()
int maxn=(1<<4)-1;//列舉第一行狀態
for(int i=0;i<=maxn;i++)
if(ans==inf) printf("impossible\n");//若ans值未改變,則無符合條件反轉次數
else printf("%d\n",ans);//若初始已全為'b'或'w',ans途中也可變為0
return 0;
}
大概就是將$4\times4$的矩陣改為$n\times n$的矩陣,$n\leq16$
將**裡的$4$改為$n$,列舉$(1<
加上空間換時間的$inline$不開o2優化,勉強從夾縫中通過
過上個題的時候還看見一道這個,就一起水過了
那就當個小常識記錄一下吧
輸入乙個字串為$0$或$1$,$1$為正面,$0$為反面
問從第乙個開始,一起翻轉前$i$個,需多少次才能都將硬幣翻成正面$1$
**很簡短,就是去除連續重複的$0$或$1$,翻轉次數k先設為長度$len-1$;
遇見重複的$k--$,末尾若為$0$,$k++$,不為$0$(就是正面)就不用翻轉
**如下:
#include using namespace std;
char s[10005];
int main()
void tarjan(int x)
else if(ii[to[i]]) ll[x]=min(ll[x],dfn[to[i]]);
}if(ll[x]==dfn[x])
}}void spfa() |$
2.如果其下標$i$大於$s_k$,它的誤差值為$2\times|m_i-m_k|$
3.如果$i$介於其之間,若介於$s_j$和$s_$之間,它的誤差值為$|2*m_i-m_j-m_j+1|$
線性$dp$
設定乙個$pre$陣列並對其進行預處理:
對於$pre[i][0]$,左邊界為$i$的向左延伸的誤差值之和;
$pre[i][n+1]$,右邊界為$i$的向右延伸的誤差值之和;
$pre[i][j]$,所選序列中$i$到$j$為連續的,$i$到$j$之間的誤差值之和
$dp[i][j]$記錄前$i$個數選取$j$個數的誤差值之和,(由於轉移方程的需要,選取的$j$個數裡面一定有第$i$個數)
#include using namespace std;
typedef long long ll;
const int maxn=100+10;
const ll inf=0x3f3f3f3f3f3f3f3f;
int n,e,k,a[maxn];
ll ans,dp[maxn][maxn],pre[maxn][maxn];
int main()
for(int i=1;i<=n;i++)
}for(int j=1;j題目描述
豬仙發現人類可以上很多大學,而豬們卻沒有大學可上。為了解決這個問題,於是他創立了一所大學,取名為豬仙大學。
為了選拔合適的學生入學,他發明了一種學術能力測試(簡稱$csat$),這種測試的分數異常精確,每頭豬的成績可以用$1$到$2,000,000,000$之間的乙個整數表示。
豬仙大學的學費很貴(豬仙比較黑),很多豬都負擔不起,他們需要申請一些獎學金($1\leq$獎學金$\leq10000$)。可是**並沒有為豬準備獎學金,於是所有的預算都必須要從學校自身有限的**中間扣除(設**總額為$f,0\leq f\leq2,000,000,000$)。
更槽的事,豬仙大學的只有$n(1\leq n\leq19999)$間教室,$n$是乙個奇數,而一共有$c(n\leq c\leq100,000)$頭豬申請入學,為了讓最多的豬接受教育,豬仙打算接受$n$頭豬的申請,而且她還想讓這些豬$cast$成績的中位數盡可能地高。
輸入格式
第一行:三個用空格分開的整數:$n,c$和$f$。
第二行到$c+1$行:每行有兩個用空格分開的整數。第乙個數是這頭豬的$cast$成績,第二個數是這頭豬想申請的獎學金。
輸出格式
第一行:乙個整數,表示豬仙可以得到的最大中位數,如果現有**不夠資助$n$頭豬,則輸出$-1$。
樣例輸入
3 5 70
30 25
50 21
20 20
5 18
35 30
樣例輸出
35
因為$n$為奇數,所以中位數處於所選豬序列當中的$n/2+1$的位置
可將求解答案的過程中分解為兩個子問題:
1.將整個豬序列按照成績由高到低排列,順次列舉最大中位數,滿足條件就退出
2.所列舉的中位數字置為$i$,第$i$頭豬的獎學金加上$i-1$左邊的$n/2$個最小獎學金之和and $i+1$右邊的$n/2$個最小獎學金之和就是當前中位數條件下所得的最小獎學金數之和;
滿足的條件即為$suml[i-1]+sumr[i+1]+e[i].money\leq e$
求解左端和右端的最小獎學金之和,可用優先佇列(預設頂位置為最大值),自動插入排序
沒了沒了 有個遺留:分數相等時,獎學金大小的先後順序對答案貌似沒有影響...
還有個問題,洛谷上的資料範圍是$2e5+10$,開$1e5+10$會$re$三個點,我還以為我邊界判斷錯誤了
#include using namespace std;
const int maxn=1e5+10;
int n,c;
typedef long long ll;
ll f,sum,suml[maxn],sumr[maxn];
priority_queueq;
struct edgee[maxn];
bool comp(edge a,edge b)
int main()
sort(e+1,e+1+c,comp);//按mark由大到小排序
n/=2;
sum=0;
for(int i=1;i<=n;i++)
suml[n]=sum;
for(int i=n+1;i<=c-n-1;i++)
suml[i]=sum;//由i向左選取n/2頭豬獎學金最小和
}sum=0;
while(!q.empty()) q.pop();//清空佇列
for(int i=c;i>=c-n+1;i--)
sumr[c-n+1]=sum;
for(int i=c-n;i>=n+2;i--)
sumr[i]=sum;//由i向右選取n/2頭豬最小獎學金之和
}for(int i=n+1;i<=c-n;i++)
}printf("-1\n");
return 0;
}
下午寫完之後交上去$90$,是因為最後判斷時右邊界寫錯了
中位數最大可達$c-n$,寫成了$c-n+1$
(列舉中位數的範圍$n+1~c-n$)
for(int i=n+1;i<=c-n;i++)
}
接下來說點閒篇,就當給自己記錄了
----------------------------------------
$ps:$
中午午歌的時候聽了$monsters$
還記得那句話$i$ $love$ $you$ $three$ $thousand$ $times.$
6 28集訓 集訓模擬賽2
第一題 n只有4,直接暴力 第二題 tarjan縮點之後跑乙個最長路 第三題 dp 第四題 思維量較大 n 的範圍很小,所以我們考慮狀壓dp 我們設 f i j k m 為第一行的狀態為 i 第二行的狀態為 j 第三行的狀態為 k 第四題的狀態為 m 所需要的最小步數 所以我們暴力列舉6重迴圈,時間...
集訓模擬賽12
今天虎哥出題變簡單了,今天本來可以寫對三個題,但是 t2 由於沒看題目,改了乙個地方就過了,t3 還把陣列開小了,導致最後少拿了超級多的分。現在後悔也沒用了,吸取教訓吧,看題 該題與題庫中 how many answers are wrong 是一樣的。刁奼接到乙個任務,為稅務部門調查一位商人的賬本...
正睿集訓2021 模擬賽3
題目描述 給定乙個序列 a 保證 a i 互不相同。你需要重新排列 a 使得 a 中任意兩個相鄰位置都包含乙個奇數和偶數。對於每個數,它的代價是 初始位置減重排後的位置 請輸出保證總代價最小的前提下,字典序最小的 a 1 leq n leq 10 5,1 leq a i leq 10 9 題目描述 ...