(排名不分先后):
Dewct http://loifrancis.gq/
zzk http://blog.csdn.net/loi__zzk
Cunese 大爷的csdn忘了,,行吧
whales http://blog.csdn.net/cherish_k
http://poj.org/problem?id=2709
杂货店出售一种由N(3<=N<=12)种不同颜色的颜料,每种一瓶(50ML),组成的颜料套装。你现在需要使用这N种颜料;不但如此,你还需要一定数量的灰色颜料。杂货店从来不出售灰色颜料——也就是它不属于这N种之一。幸运的是,灰色颜料是比较好配置的,如果你取出三种不同颜色的颜料各x ml,混合起来就可以得到xml的灰色颜料(注意不是3x)。
现在,你知道每种颜料各需要多少ml。你决定买尽可能少的“颜料套装”,来满足你需要的这N+1种颜料。那么你最少需要买多少个套装呢?
输入描述 输入包含若干组测试数据。每组数据一行:第一个数N, 3<=N<=12, 含义如上;接下来N+1个数,分别表示你需要的N+1种颜料的毫升数。最后一种是灰色。所有输入的毫升数<=1000.
注意:输入中不存在每个颜料套装的毫升数。由题意可知,每种各50ml,即一共50N ml
输出描述 每组数据输出一行,最少需要的套装数。
样例输入 3 40 95 21 0
7 25 60 400 250 0 60 0 500
4 90 95 75 95 10
5 0 0 0 0 0 333
0
样例输出 2
8
2
4
数据范围及提示 对于30%的数据 N=3
对于100%的数据3 <= N <= 100
数据最多不超过10组
先不考虑灰色,满足其他颜料至少需要ans;
每次操作,选取剩余颜料最多的三种,合成1单位灰色颜料,重新sort;
若不足三种且未合成足够的灰色,则ans++,每种颜料加50
直接sort的std
#include
#include
#include
using namespace std;
int maxx,ans,n,gry;
int b[10000];
void init(){
maxx=0;
ans=0;
}
bool cmp(int a,int b){
return a>b;
}
int main(){
while(scanf("%d",&n)!=EOF){
if(n==0) return 0;
init();
for(int i=1;i<=n;i++) scanf("%d",&b[i]),maxx=max(maxx,b[i]);
scanf("%d",&gry);
ans=maxx/50;
if(maxx%50) ans++,maxx=ans*50;
for(int i=1;i<=n;i++) b[i]=maxx-b[i];
sort(b+1,b+n+1,cmp);
while(gry>0){
if(b[3]==0){
ans++;
for(int i=1;i<=n;i++) b[i]+=50;
}
b[1]--,b[2]--,b[3]--,gry--;
sort(b+1,b+n+1,cmp);
}
printf("%d\n",ans);
}
}
我的cpp在poj上WA。。。。。随机数据太良心
考场代码需要改正的是:
1.记录每种颜料标号是不必要的,因为颜料的种类是无意义的,我们只关心它们是否不同。
2.没有特判灰色等于0,在剩余颜料不满两种的情况下,ans会+1;
调了一下午啊!!!!!!
考场 堆
#include
#include
#include
#include
using namespace std;
const int N=150;
int maxx,n,ned[N],ml[N],gry,cnt,ans;
struct node{
int id,num;
}tmp[5];
priority_queue Q;
bool operator <(node a,node b){
return a.numvoid done(){
ans=maxx/50;
if(maxx%50) ans++,maxx=ans*50;
for(int i=1;i<=n;i++){
if(maxx-ned[i])
Q.push((node){i,maxx-ned[i]});
}
if(Q.size()<=2){
ans++;
for(int i=1;i<=n;i++) ml[i]=50;
while(!Q.empty()){
node u=Q.top();
Q.pop();
ml[u.id]+=u.num;
}
for(int i=1;i<=n;i++){
Q.push((node){i,ml[i]});
}
}
while(!Q.empty()){
for(int i=1;i<=3;i++){
tmp[i]=Q.top();
Q.pop();
}
cnt+=1;
if(cnt>=gry) return ;
for(int i=1;i<=3;i++){
if(tmp[i].num-1)
Q.push((node){tmp[i].id,tmp[i].num-1});
}
if(Q.size()<=2){
ans++;
for(int i=1;i<=n;i++) ml[i]=50;
while(!Q.empty()){
node u=Q.top();
Q.pop();
ml[u.id]+=u.num;
}
for(int i=1;i<=n;i++){
Q.push((node){i,ml[i]});
}
}
}
return ;
}
void init(){
while(!Q.empty()) Q.pop();
ans=0;
maxx=0;
cnt=0;
for(int i=1;i<=3;i++) tmp[i].id=0,tmp[i].num=0;
}
int main(){
freopen("painter.in","r",stdin);
freopen("painter.out","w",stdout);
while(scanf("%d",&n)!=EOF){
if(n==0) return 0;
init();
for(int i=1;i<=n;i++) {
scanf("%d",&ned[i]);
maxx=max(maxx,ned[i]);
}
scanf("%d",&gry);
done();
printf("%d\n",ans);
}
return 0;
}
改 √ 了的堆
#include
#include
#include
#include
using namespace std;
const int N=150;
int maxx,n,ned[N],ml[N],gry,cnt,ans,tot;
int tmp[5];
priority_queue<int> Q;
void add(){
ans++;
tot=0;
for(int i=1;i<=n;i++) ml[i]=50;
while(!Q.empty()){
int u=Q.top();
Q.pop();
ml[++tot]+=u;
}
for(int i=1;i<=n;i++){
Q.push(ml[i]);
}
}
void done(){
ans=maxx/50;
if(maxx%50) ans++,maxx=ans*50;
if(gry==0) return ;//!!!!!!!!!!
for(int i=1;i<=n;i++){
if(maxx-ned[i]>0)
Q.push(maxx-ned[i]);
}
if(Q.size()<=2){
add();
}
while(!Q.empty()){
for(int i=1;i<=3;i++){
tmp[i]=Q.top();
Q.pop();
}
cnt+=1;
if(cnt>=gry) return ;
for(int i=1;i<=3;i++){
if(tmp[i]-1>0)
Q.push(tmp[i]-1);
}
if(cnt2){
add();
}
}
}
void init(){
while(!Q.empty()) Q.pop();
ans=0;
maxx=0;
cnt=0;
}
int main(){
while(scanf("%d",&n)!=EOF){
if(n==0) return 0;
init();
for(int i=1;i<=n;i++) {
scanf("%d",&ned[i]);
maxx=max(maxx,ned[i]);
}
scanf("%d",&gry);
done();
printf("%d\n",ans);
}
return 0;
}
http://hzwer.com/4598.html
给出数字N(1<=N<=10000),X(1<=x<=1000),Y(1<=Y<=1000),代表有N个敌人分布一个X行Y列的矩阵上,矩形的行号从0到X-1,列号从0到Y-1再给出四个数字x1,y1,x2,y2,代表你要从点(x1,y1)移到(x2,y2)。在移动的过程中你当然希望离敌人的距离的最小值最大化,现在请求出这个值最大可以为多少,以及在这个前提下,你最少要走多少步才可以回到目标点。注意这里距离的定义为两点的曼哈顿距离,即某两个点的坐标分为(a,b),(c,d),那么它们的距离为|a-c|+|b-d|。
输入描述 第一行给出数字N,X,Y
第二行给出x1,y1,x2,y2
下面将有N行,给出N个敌人所在的坐标
输出描述 在一行内输出你离敌人的距离及在这个距离的限制下,你回到目标点最少要移动多少步。
样例输入 2 5 6
0 0 4 0
2 1
2 3
样例输出 2 14
数据范围及提示
30%: n=1
100%: 1<=n<=1000, 1<=x<=1000, 1<=y<=1000
预处理出每个点到它最近敌人的距离(把敌人坐标丢进队列里,做bfs),将整张图扫一遍。
二分答案,按照预处理出的距离,判断某点是否能走,bfs;
注意:
二分判断时,首先判断起点是否合法!!
考试的时候,没有预处理,每二分一次重新标记图,成功tle!
#include
#include
#include
#include
#include
using namespace std;
struct node{
int x,y,step;
};
bool used[1005][1005];
int dis[1005][1005];
queue Q;
int n,X,Y,x1,x2,y1,y2,ans,a,b;
int dx[10]={0,1,0,-1,0},dy[10]={0,0,1,0,-1};
bool can(int x,int y,int mid){
if(x>=0&&x=0&&y=mid) return true;
return false;
}
void init(int mid){
memset(used,0,sizeof(used));
while(!Q.empty()) Q.pop();
ans=0;
}
bool check(int x){
init(x);
Q.push((node){x1,y1,0});
used[x1][y1]=1;
if(dis[x1][y1]return false;
while(!Q.empty()){
node u=Q.front();
if(u.x==x2&&u.y==y2){
ans=u.step;
return true;
}
Q.pop();
for(int i=1;i<=4;i++){
int xx=u.x+dx[i],yy=u.y+dy[i];
if(can(xx,yy,x)){
used[xx][yy]=1;
Q.push((node){xx,yy,u.step+1});
}
}
}
return false;
}
void done(){
while(!Q.empty()){
node u=Q.front();
Q.pop();
for(int i=1;i<=4;i++){
int xx=u.x+dx[i],yy=u.y+dy[i];
if(xx>=0&&xx=0&&yy1;
used[xx][yy]=1;
Q.push((node){xx,yy,u.step+1});
}
}
}
return ;
}
int main(){
freopen("escape.in","r",stdin);
freopen("escape.out","w",stdout);
scanf("%d%d%d",&n,&X,&Y);
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
for(int i=1;i<=n;i++){
scanf("%d%d",&a,&b);
Q.push((node){a,b,0});
dis[a][b]=0;
used[a][b]=1;
}
done();
int l=-1,r=100000000+800;
while(r-l>1){
int mid=r+l>>1;
if(check(mid)) l=mid;
else r=mid;
}
check(l);
printf("%d %d\n",l,ans);
return 0;
}
https://vjudge.net/problem/POJ-1837
有一个天平,天平左右两边各有若干个钩子,总共有C个钩子,有G个钩码,求将钩码全部挂到钩子上使天平平衡的方法的总数。
输入描述 第一行两个数c, g分别代表钩子数和钩码数
第二行c个数,表示每个钩子距离天平中央的距离c[i],负数表示在左边,正数表示在右边
第三行g个数,表示每个钩码的重量w[i]
输出描述 输出总方案数
样例输入
2 4
-2 3
3 4 5 8
样例输出 2
数据范围及提示 30%: c<=9, g<=9
100%: c<=20, g<=20, -15<=c[i]<=15, w[i]<=25
一道精彩的初中物理题
设置状态dp[i][j]表示放了i个钩码,平衡度为j的方案数;
平衡度的定义为:右边-左边
由此可知:左边重 j<0,右边重 j>0,平衡 j=0
由数据范围可以推测出,平衡度的绝对值小于7500
为了避免负数作为下标,将平衡度均+7500
枚举钩码
枚举放在哪个位置
枚举此时的平衡度
转移
总结一下,本题主要难在设计状态。
#include
#include
#include
using namespace std;
int g[25],w[25],dp[25][15020];
int n,m;
int main(){
freopen("balance.in","r",stdin);
freopen("balance.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&g[i]);
for(int i=1;i<=m;i++) scanf("%d",&w[i]);
dp[0][7500]=1;
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
for(int k=0;k<=15000;k++){
if(k-w[i]*g[j]>=0)
dp[i][k]+=dp[i-1][k-w[i]*g[j]];
}
}
}
printf("%d",dp[m][7500]);
return 0;
}
result 100+40+0;
T1由于数据水,成绩不准确;