考前做題筆記

FinderHT發表於2024-10-18

[KDOI-10]商店砍價

考慮dp,欽定全用操作 \(1\),容易由 \(v_i\le 10^5\) 發現只有剩下的數位小於 \(6\) 時用操作 \(2\) 才更優。於是我們設 \(f_{i,j}\) 為考慮完第 \(i\) 位剩下 \(j\) 個數用操作 \(2\) 能減小的最大代價,並從高位向低位考慮。

轉移方程很顯然,選或不選用操作 \(2\) 能減小的代價取最大值,對於數位 \(x\) 剩下 \(j\) 位,因為是從低到高列舉用操作 \(2\) 即保留這一位的代價為 \(x\times 10^{j-1}\)。所以轉移方程為 $$f_{i,j}=\max(f_{i+1,j},f_{i+1,j-1}+v_i-a_i\times 10^{j-1})$$ \(a_i\) 為輸入數從左向右數第 \(i\) 位。

Code:

#include<bits/stdc++.h>
#define gt getchar
#define pt putchar
#define int long long
#define ull unsigned long long
#define fst first
#define snd second
#define L(x) x<<1
#define R(x) x<<1|1
using namespace std;
typedef pair<int,int> pii;
const double eps=1e-6;
inline bool pts(char ch){return ch>=48&&ch<=57;}
inline int read(){
	bool f=0;int x=0;char ch;
	ch=gt();
	while(!pts(ch)&&ch!=EOF){if(ch=='-')f=1;ch=gt();}
	while(pts(ch)){x*=10;x+=(ch-48);ch=gt();}
	if(f)return -x;
	else return x;
}
template<class T>
inline void print(T x){
	char s[114];
	int top=0;
	if(x<0)pt('-');
	do{
		top++;
		if(x>=0)s[top]=(x%10)+48;
		else s[top]=(-(x%10)+48);
		x/=10;
	}while(x);
	while(top){pt(s[top]);top--;}
}
int f[100005][10];
int v[10];
//|n|>5時1一定優,設f[i][j]為考慮到第i位利用策略二答案減小的值
void solve(){
    memset(f,-1,sizeof(f));
    string s;
    cin>>s;
    int len=s.size();
    s=' '+s;
    int sum=0;
    for(int i=1;i<=9;i++)v[i]=read();
    f[len+1][0]=0;
    for(int i=len;i>=1;i--){
        sum+=v[s[i]-'0'];
        f[i][0]=f[i+1][0];
        for(int j=1;j<=5;j++){
            f[i][j]=max(f[i][j],f[i+1][j]);
            f[i][j]=max(f[i+1][j],f[i+1][j-1]+v[s[i]-'0']-(s[i]-'0')*(int)powl(10,j-1));
        }
    }
    int maxn=-1;
    for(int j=1;j<=5;j++)
        maxn=max(maxn,f[1][j]);
    cout<<min(sum,sum-maxn)<<'\n';
}
signed main(){
    int c=read(),T=read();
    while(T--)solve();
    return 0;
}

打字練習

把範文和輸入分別讀入,讀入時用 getline,然後把每行字串處理掉退格鍵加入到 vector 中方便比較,記正確的字元數為 \(cnt\),答案即為 \(cnt\times 60\div t+0.5\)

坑點:範文也有退格鍵,處理退格時注意寫法。

#include<bits/stdc++.h>
#define gt getchar
#define pt putchar
#define int long long
#define ull unsigned long long
#define fst first
#define snd second
#define L(x) x<<1
#define R(x) x<<1|1
using namespace std;
typedef pair<int,int> pii;
const double eps=1e-6;
inline bool pts(char ch){return ch>=48&&ch<=57;}
inline int read(){
	bool f=0;int x=0;char ch;
	ch=gt();
	while(!pts(ch)&&ch!=EOF){if(ch=='-')f=1;ch=gt();}
	while(pts(ch)){x*=10;x+=(ch-48);ch=gt();}
	if(f)return -x;
	else return x;
}
template<class T>
inline void print(T x){
	char s[114];
	int top=0;
	if(x<0)pt('-');
	do{
		top++;
		if(x>=0)s[top]=(x%10)+48;
		else s[top]=(-(x%10)+48);
		x/=10;
	}while(x);
	while(top){pt(s[top]);top--;}
}
string fw[10005];
string sr[10005];
vector<char>v1[10005],v2[10005];
signed main(){
    int cnt=0;
    while(true){   
        cnt++;
        getline(cin,fw[cnt]);
        if(fw[cnt]=="EOF")break;
        for(char c:fw[cnt]){
            if(c!='<')v1[cnt].push_back(c);
            else if(c=='<'&&v1[cnt].size()>0)v1[cnt].pop_back();//這兩個if else順序是坑點
        }
    }
    int tnc=0;
    while(true){
        tnc++;
        getline(cin,sr[tnc]);
        if(sr[tnc]=="EOF")break;
        for(char c:sr[tnc]){
            if(c!='<')v2[tnc].push_back(c);
            else if(c=='<'&&v2[tnc].size()>0)v2[tnc].pop_back();
        }
    }
    int ans=0;
    for(int i=1;i<=min(cnt,tnc);i++)
        for(int j=0;j<min(v2[i].size(),v1[i].size());j++)
            if(v1[i][j]==v2[i][j])ans++;
            //cout<<(char)v1[i][j]<<' '<<(char)v2[i][j]<<'\n';
    int T=read();
    cout<<(int)(1.0*ans/T*60.0+0.5);
    return 0;
}