2018.02.08【GDOI2018】模擬C組
阿新 • • 發佈:2019-02-16
終於結束了。。。
JZOJ NO.1 【GDOI2005】積木分發
作為最水的一道題。快排需要的積木,從小到大模擬,給不了NO,否則就YES。
#pragma GCC optimize(2)
#include <cstdio>
#include <algorithm>
#include <cctype>
using namespace std;
struct b{int x,y;}a[10002]; int n; unsigned long long s;
bool cmp(b u,b v){return u.y<v.y;}
unsigned long long in(){
char c=getchar(); unsigned long long ans=0;
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
bool check(int s){
for (int i=1;i<=n;i++){
if (s<a[i].y) return false;//不能幫助
s+=a[i].x;//收回積木
} return true;
}
int main(){
while (n=in(),s=in(),n||s){//記住或者(二十分!)
for (int i=1;i<=n;i++) a[i].x=in(),a[i].y=in();
stable_sort(a+1,a+1+n,cmp);
if (check(s)) puts("YES"); else puts("NO");
}
return 0;
}
JZOJ NO.2 【GDOI2005】電路穩定性
純模擬,並聯電路x×y ,串聯電路x+(1-x)×y
網際網路好像無所不能,我們在網上搜集學習資料,查詢相關資訊……
進入正題。
#include <cstdio>
#include <cstring>
#include <cctype>
using namespace std;
double a[101],p[27]; char s[101]; int n;
int news(){int m=0; for (int i=1;i<=n;i++) if (a[i]) a[++m]=a[i]; a[m+1]=0; return m;}//把0都去掉
int main(){
scanf("%d\n",&n);
scanf("%s",s+1);
for (int i=1;i<=n;i++) scanf("%lf",&p[i]); n=strlen(s+1);
for (int i=1;i<=strlen(s+1);i++){
if (s[i]=='(') a[i]=-1;//(變成-1
if (s[i]==')') a[i]=-2;//以此類推
if (s[i]==',') a[i]=-3;
if (isupper(s[i]))a[i]=p[s[i]-64];//大寫字母變成它對應的權值
}
while (n>1){
for (int i=1;i<=n;i++){
int j=i;
while (a[j]>0&&a[j-1]!=-3&&a[j+1]==-3&&a[j+2]>0){//串聯
a[j+2]=a[j]+(1-a[j])*a[j+2];//串聯公式
a[j+1]=a[j]=0,j+=2;//變成0
}
}
n=news();//清掃運算過程
for (int i=2;i<=n;i++){
int j=i;
while (a[j-1]==-1&&a[j+1]==-2&&a[j+2]==-1&&a[j+4]==-2){//並聯
a[j+3]*=a[j];//並聯公式
a[j-1]=a[j+1]=a[j]=0,j+=3;
}
if (a[j-1]==-1&&a[j+1]==-2&&(a[j+2]==-3||a[j+2]==-2||!a[j+2])) a[j-1]=a[j+1]=0;//刪掉括號
}
n=news();//清掃運算過程
}
printf("%.4lf",a[1]);//剩下一個就是答案
return 0;
}
JZOJ NO.3 【GDOI2005】飛越原野
廣搜,飛行和行走
用一個迴圈佇列儲存座標、能量、答案。
布林陣列儲存是否走過,三維,下標為座標和能量。
#pragma GCC optimize(3)
#include <cstdio>
using namespace std;
bool v[101][101][101]; char map[101][101];
const int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
struct node{
int x,y,ans,eneg;
}q[320001];
void bfs(int n,int m,int d){
int head=0,tail=0;
node f1,f2;
f1.x=f1.y=1,f1.ans=0,f1.eneg=d;//一開始初值能量滿,座標起點
q[++tail]=f1;
while (head!=tail){
f1=q[++head];//出隊
head=(head-1)%(32*n*m)+1;
if (f1.x==n&&f1.y==m) {printf("%d",f1.ans);return;}//到達終點
for (int i=0;i<4;i++){//走路
f2.x=f1.x+dx[i]; f2.y=f1.y+dy[i];
if (f2.x>0&&f2.x<=n&&f2.y>0&&f2.y<=m&&!v[f2.x][f2.y][f1.eneg]&&map[f1.x][f1.y]=='P'){//可以著陸
f2.ans=f1.ans+1;//步數+1
f2.eneg=f1.eneg;//能量不變
v[f2.x][f2.y][f2.eneg]=1;//標記
q[++tail]=f2;//入隊
tail=(tail-1)%(32*n*m)+1;
}
}
for (int j=2;j<=f1.eneg;j++){//飛行距離
for (int i=0;i<4;i++){
f2.x=f1.x+dx[i]*j;
f2.y=f1.y+dy[i]*j;
if (f2.x>0&&f2.x<=n&&f2.y>0&&f2.y<=m&&!v[f2.x][f2.y][f1.eneg-j]&&map[f1.x][f1.y]=='P'){//可以著陸
f2.ans=f1.ans+1;//步數+1
f2.eneg=f1.eneg-j;//減去消耗的能量
v[f2.x][f2.y][f2.eneg]=1;
q[++tail]=f2;//入隊
tail=(tail-1)%(32*n*m)+1;
}
}
}
}
puts("impossible"); return;//不可能到達
}
int main(){
int n,m,d;
scanf("%d%d%d\n",&n,&m,&d);
for (int i=1;i<=n;i++) gets(map[i]+1);
bfs(n,m,d); return 0;
}
JZOJ NO.4 【GDOI2005】電子眼
一開始看錯題目,輸出n-1,錯了。&_&
原來是樹形dp,如果這個路口裝,那麼與它相連的路口不用裝,如果這個路口不裝,那麼與它相連的路口都要裝。
#pragma GCC optimize(2)
#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;
int n,f[100001][2],ls[100001],a[200001];
bool v[100001];
int in(){
char c=getchar(); int ans=0;
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
void dp(int x){
int s1=1,s2=0;
for (int i=ls[x-1];i<=ls[x]-1;i++){
if (!v[a[i]]){
v[a[i]]=1;//來過。
dp(a[i]);
s1+=min(f[a[i]][0],f[a[i]][1]);//裝選擇最小的
}
s2+=f[a[i]][1];//不裝其它都要裝
}
f[x][1]=s1;
f[x][0]=s2;
}
int main(){
n=in(); ls[0]=1;
for (int i=1;i<=n;i++){
int x=in(); ls[i]=ls[i-1];
for (int j=ls[i];j<=ls[i]+x-1;j++) a[j]=in();
ls[i]+=x;} //ls儲存每個路口的路佔用的位置
v[1]=1; dp(1);
printf("%d",min(f[1][0],f[1][1])); return 0;//裝和不裝的最大值
}