2021-TKK-ICPC Summer Training Camp Round #1 題解
阿新 • • 發佈:2021-08-01
1:消滅星星
解析
最優策略是隻消滅一種顏色,最後一次性消滅另外一種顏色。據此策略,取兩種情況的最小值即可。
標程
void solve(){ int n,m; scanf("%d%d",&n,&m); int a0=0,a1=0; int f=-1; for(int i=1;i<=n;i++){ int x; scanf("%d",&x); if(f!=x){ if(x==0){ a0++; f=0; } else{ a1++; f=1; } } } int res=min(a0,a1)+1; if(res<=m)printf("YES\n"); else printf("NO\n"); }
2: 下館子 -3
解析
答案是最後出勤次數最多,且出勤次數最先大於等於max次的同學。
考慮用map對字串做對映,最後算出最大值\(max\)。然後將出勤次數為\(max\)同學放入set集合。
重新遍歷一次,當出現出勤次數大於等於\(max\),判斷是否在set集合之中即可。
程式碼
#include<bits/stdc++.h> #include<set> #include<map> typedef long long ll; using namespace std; pair<string,int>r[100005]; set<string>st; map<string,int>mp; //標程 void solve(){ st.clear(); mp.clear(); int n ; scanf("%d",&n); int mx=INT_MIN; string res="null"; for(int i=1;i<=n;i++){ string s; int x; cin>>s>>x; r[i]={s,x}; mp[s]+=x; } for(auto i:mp){ mx=max(mx,i.second); } for(auto i:mp){ if(i.second==mx){ st.insert(i.first); } } mp.clear(); for(int i=1;i<=n;i++){ string name=r[i].first; int score=r[i].second; mp[name]+=score; if(mp[name]>=mx && st.count(name)){ res=name; break; } } cout<<res; } int main() { solve(); return 0; }
3:光照強度-2
解析
根據資料量,考慮O(N)的dp解法。
- 規定:\(r[i][j]\)代表\([i,j]\)的明亮度,\(g[i][j]\)代表\([i,j]\)處的燈泡亮度,\(g[i][j]=0\)代表此處沒有燈泡
- 假設方格\([i,j]\)沒有燈,且上下左右的方格的明亮度(燈和明亮度等價的)分別如圖所示。
此位置的明亮度由4個方向遞減而來。
- 左邊:能貢獻\(2-1=1\)的明亮度
- 上邊:能貢獻\(4-1=3\)的明亮度
- 右邊:能貢獻\(3-1=2\)的明亮度
- 下邊:能貢獻$5-1=4 $的明亮度
因此此處的明亮值為\(max(1,3,2,4)\)
- 如果方格\([i,j]\)有一盞燈,\(g[x][y]=5\)
此處的明亮值為\(max(1,3,2,4,g[x][y])=5\)
因此我們可以推斷出狀態轉移方程。
\[r[i][j]=max(g[i][j],r[i+1][j],r[i][j+1],r[i-1][j],r[i][j-1],r[i][j]) \]但是,如果只從左上角開始遍歷一次,第一次遍歷到某個點的時候,下方和右方沒有資料,因此要從4個方向維護每個位置的最大值。
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
typedef pair<int,int>pii;
const int N =1005;
int r[N][N];
int g[N][N];
void solve(){
int a,b,m;
scanf("%d%d%d",&a,&b,&m);
for(int i=1;i<=m;i++){
int x,y,c;
scanf("%d%d%d",&x,&y,&c);
g[x][y]=max(g[x][y],c);
}
//左上角
for(int i=1;i<=a;i++){
for(int j=1;j<=b;j++){
int q=r[i-1][j]-1,p=r[i][j-1]-1;
int t=max(0,max(q,p));
r[i][j]=max(max(g[i][j],t),r[i][j]);
}
}
//右下角
for(int i=a;i>=1;i--){
for(int j=b;j>=1;j--){
int q=r[i+1][j]-1,p=r[i][j+1]-1;
int t=max(0,max(q,p));
r[i][j]=max(max(g[i][j],t),r[i][j]);
}
}
//右上角
for(int i=1;i<=a;i++){
for(int j=b;j>=1;j--){
int q=r[i-1][j]-1,p=r[i][j+1]-1;
int t=max(0,max(q,p));
r[i][j]=max(max(g[i][j],t),r[i][j]);
}
}
//左下角
for(int i=a;i>=1;i--){
for(int j=1;j<=b;j++){
int q=r[i+1][j]-1,p=r[i][j-1]-1;
int t=max(0,max(q,p));
r[i][j]=max(max(g[i][j],t),r[i][j]);
}
}
for(int i=1;i<=a;i++){
for(int j=1;j<=b;j++){
if(j!=1)printf(" ");
printf("%d",r[i][j]);
}
printf("\n");
}
}
int main() {
solve();
return 0;
}