動態

詳情 返回 返回

12.21考試總結 - 動態 詳情

分數

題號 T1 T2 T3 T4 T5 T6 T7 總分
分數 100 100 100 20 100 100 64 584

分析

T1

模板,講爛了

點擊查看代碼
#include<bits/stdc++.h>
#define int long long
#define endl "\n"
using namespace std;
const int maxn=1e6+5,mod=1e9+7,inf=1e18;
int n,a[maxn],dp[maxn];
signed main(){
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	int maxi=-inf;
	for(int i=1;i<=n;i++){
		dp[i]=1;
		for(int j=1;j<i;j++){
			if(a[j]<a[i]){
				dp[i]=max(dp[i],dp[j]+1);
			}
		}
		maxi=max(maxi,dp[i]);
	}
	cout<<maxi<<endl;
	return 0;
}

T2

二維DP模板,也講爛了

Tip:注意行列為偶數時不能走

點擊查看代碼
#include<bits/stdc++.h>
#define int long long
#define endl "\n"
using namespace std;
const int maxn=1e3+5,mod=1e9+7,inf=1e18;
int n,m,dp[maxn][maxn];
signed main(){
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>n>>m;
	dp[1][1]=1;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(i==1&&j==1)continue;
			if(i%2==0&&j%2==0)continue;
			dp[i][j]=dp[i-1][j]+dp[i][j-1];
		} 
	} 
	cout<<dp[n][m]<<endl;
	return 0;
}

T3

\(10^{-9}\)點意思。

  1. 定義狀態:\(dp_i\)表示恰好得到\(i\)個字的最少操作次數
  2. 答案:\(dp_n\)
  3. 狀態轉移方程:
    ①:從\(i-1\)轉移過來:\(dp_{i-1}+1\)
    ②:當\(i\)為偶數時,從\(\frac{i}{2}\)轉移過來:\(dp_{\frac{i}{2}}+1\)
    答案即:
    (1)\(i\mod 2=1\)\(dp_i=dp_{i-1}+1\)
    (2)\(i\mod 2=0\)\(dp_i=\min(dp_{i-1}+1,dp_{\frac{i}{2}}+1)\)
  4. 邊界:\(dp_1=1\)
點擊查看代碼
#include<bits/stdc++.h>
#define int long long
#define endl "\n"
using namespace std;
const int maxn=1e6+5,mod=1e9+7,inf=1e18;
int n,dp[maxn]; 
signed main(){
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>n;
	memset(dp,0x3f,sizeof(dp));
	dp[1]=0;
	for(int i=2;i<=n;i++){
		dp[i]=min(dp[i],dp[i-1]+1);
		if(i%2==0){
			dp[i]=min(dp[i],dp[i/2]+1); 
		} 
	} 
	cout<<dp[n]<<endl;
	return 0;
}

T4

典例題,只不過將01揹包的模板\(c\)數組改為打贏一個值,打輸一個值而已
注意:這裏由於前面的與後面的有關,所以不能改成一個一維數組的優化(喜提20分……)

點擊查看代碼
#include<bits/stdc++.h>
#define int long long
#define endl "\n"
using namespace std;
const int maxn=1e3+5,mod=1e9+7,inf=1e18;
int n,m,win[maxn],lose[maxn],use[maxn],dp[maxn][maxn];
signed main(){
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>lose[i]>>win[i]>>use[i];
	}
	for(int i=1;i<=n;i++){
		for(int j=0;j<=m;j++){
			if(j>=use[i]){
				dp[i][j]=max(dp[i-1][j]+lose[i],dp[i-1][j-use[i]]+win[i]);
			}
			else{
				dp[i][j]=dp[i-1][j]+lose[i];
			}
		}
	}
	cout<<dp[n][m]*5<<endl;
	return 0;
}

T5

這裏我用記搜寫的
定義\(dfs(pos,x)\)表示第\(x\)此傳球在第\(pos\)個人手上
那麼只要判斷x=1時pos是否也等於1即可
注意,環形,所以1號左邊是\(n\)號,\(n\)號右邊是一號

點擊查看代碼
#include<bits/stdc++.h>
#define int long long
#define endl "\n"
using namespace std;
const int maxn=1e3+5,mod=1e9+7,inf=1e18;
int n,m,dp[maxn][maxn],ans[maxn];
int gl(int x){
	if(x==1){
		return n;
	}
	return x-1;
}
int gr(int x){
	if(x==n){
		return 1;
	}
	return x+1;
}
int dfs(int pos,int x){
	if(x==1){
		if(pos==1){
			return 1;
		}
		return 0; 
	}
	if(dp[pos][x]!=-1){
		return dp[pos][x];
	} 
	int anss=dfs(gl(pos),x-1)+dfs(gr(pos),x-1);
	dp[pos][x]=anss;
	return anss;
}
signed main(){
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>n>>m;
	memset(dp,-1,sizeof(dp));
	cout<<dfs(1,m+1)<<endl;
	return 0;
}

T6

最大正方形的改版,只不過加一個維度表示右下角的數是1還是0
如果數是0,則答案需要:
左邊的以1為右下角的滿足條件的正方形邊長與
上方的以1為右下角的滿足條件的正方形邊長與
左上角的以0為右下角的滿足條件的正方形邊長
作比較,取最小值

同理,如果數是1,則答案需要:
左邊的以0為右下角的滿足條件的正方形邊長與
上方的以0為右下角的滿足條件的正方形邊長與
左上角的以1為右下角的滿足條件的正方形邊長
作比較,取最小值

點擊查看代碼
#include<bits/stdc++.h>
#define int long long
#define endl "\n"
using namespace std;
const int maxn=2e3+5,mod=1e9+7,inf=1e18;
int n,m,a[maxn][maxn],dp[maxn][maxn][2];
signed main(){
//	freopen("test.in","r",stdin);
//	freopen("test.out","w",stdout);
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			char c;
			cin>>c;
			a[i][j]=c-'0';
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			dp[i][j][a[i][j]]=1;
		}
	}
	int maxi=-inf;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(a[i][j]==1){
				dp[i][j][1]=min(dp[i-1][j][0],min(dp[i][j-1][0],dp[i-1][j-1][1]))+1;
				maxi=max(maxi,dp[i][j][1]);
			}
			else{
				dp[i][j][0]=min(dp[i-1][j][1],min(dp[i][j-1][1],dp[i-1][j-1][0]))+1;
				maxi=max(maxi,dp[i][j][0]);
			}
		}
	}
	cout<<maxi<<endl;
	return 0;
}

T7

同樣也是最大正方形的改版

可以發現,如果想要從一個正方形擴大,需要右下角為1,其餘都為0,定義兩個數組,分別表示一個位置左邊0的個數與上方0的個數(包括自己)
則答案為:
左邊的以0為的個數與
上方的以0的個數與
左上角的以1為右下角的滿足條件的正方形邊長
作比較,取最小值
坑點:
由於是對角線,所以左右兩邊的對角線都要考慮,右邊同理

點擊查看代碼
#include<bits/stdc++.h>
#define int long long
#define endl "\n"
using namespace std;
const int maxn=2e3+5e2+5,mod=1e9+7,inf=1e18;
int n,m,a[maxn][maxn],dp[maxn][maxn],pd[maxn][maxn][2],dp1[maxn][maxn];
signed main(){
//	freopen("test.in","r",stdin);
//	freopen("test.out","w",stdout);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			char c;
			cin>>c;
			a[i][j]=c-'0';
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(a[i][j]==1){
				dp[i][j]=1;
			}
		}
	}
//	cout<<"haha1";
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(a[i][j]==0){
				pd[i][j][0]=pd[i][j-1][0]+1;
				pd[i][j][1]=pd[i-1][j][1]+1;
			}
		}
	}
	int maxi=0;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(a[i][j]==1){
				dp1[i][j]=min(dp1[i-1][j-1],min(pd[i][j-1][0],pd[i-1][j][1]))+1;
				maxi=max(maxi,dp1[i][j]);
			}
		}
	}
//	cout<<"haha2"; 
	memset(pd,0,sizeof(pd));
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(a[i][j]==1){
				dp1[i][j]=1;
			}
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=m;j>=1;j--){
			if(a[i][j]==0){
				pd[i][j][0]=pd[i][j+1][0]+1;
				pd[i][j][1]=pd[i-1][j][1]+1;
			}
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(a[i][j]==1){
				dp1[i][j]=min(dp1[i-1][j+1],min(pd[i][j+1][0],pd[i-1][j][1]))+1;
				maxi=max(maxi,dp1[i][j]);
			}
		}
	}
	cout<<maxi;
	return 0;
}
/*
4 4
1 0 0 1
0 0 1 0
0 1 0 1
1 0 0 0
*/ 
user avatar pihome 頭像 yjxmike 頭像
點贊 2 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.