万事万物,讲究一个取舍,做题如此,人生亦是如此
在n<=10的数据范围,1<=a,b<=5的情况下,你是仅仅着眼于眼前的题目,还是想要把它推广到更大的范围去呢
取舍
我尝试了3个小时,可是一直WA,结果随手写了一发暴力AC
我认为,人为设置循环上限的办法终究不是好办法,我还是更加倾向于直接得出答案的办法
我在想,陷入循环的时候就意味着存在两个时刻,这两个时刻表示的局面是一样的。
我只需要知道怎样来表示这个局面,把以往的局面都存起来,然后每次查询新局面即可
当然,我不会让时间一分一秒流逝
我每一次跳跃到最近一个在与睡魔抗争的同学的时间点上
为了记录下局面,我维护了一个vector来告诉我每一个同学离抗争的时间点还有多久
当然,我把他们都放入了set,来查询
我认为,一旦存在两个时间点使得我维护的vector一样,那么这个时间便会无止境的循环下去
可是,事实告诉我,我错了
尽管如此,我依然觉得我的想法是正确的,只是缺少关键的数据
放下你的执念吧!你还有远方的诗和田野
我暂且把此题放下,因为我深知
我的100道动态规划才完成了1/4
以下是暴力解法:
#include <iostream>
using namespace std;
int n,a[12],b[12],c[12],kcase=1,slnum;
bool flag=false;
int main(){
ios_base::sync_with_stdio(false);
while(cin>>n&&n){
for(int i=0;i<n;++i)
cin>>a[i]>>b[i]>>c[i];
for(int i=1;i<=100000;++i){
slnum=0;
for(int j=0;j<n;++j)
if(c[j]>a[j])
++slnum;
if(slnum==0){
cout<<"Case "<<kcase++<<": "<<i<<endl;
flag=true;
break;
}
for(int j=0;j<n;++j)
if(c[j]==a[j])
c[j]=(slnum>n-slnum)?c[j]+1:1;
else if(c[j]==a[j]+b[j])
c[j]=1;
else
++c[j];
}
if(!flag)
cout<<"Case "<<kcase++<<": -1\n";
flag=false;
}
return 0;
}
以下那令我遗憾的未AC!!!解法:
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
using namespace std;
set<vector<int>> se;
vector<int> v;
int n,c,a[12],b[12],ans,kcase=1;
bool judge();
int main(){
ios_base::sync_with_stdio(false);
while(cin>>n&&n){
v.resize(n);
for(int i=0;i<n;++i){
cin>>a[i]>>b[i]>>c;
v[i]=(a[i]>=c)?a[i]-c:(a[i]<<1)+b[i]-c;
}
while(judge());
cout<<"Case "<<kcase++<<": "<<ans+1<<endl;
se.clear();
}
return 0;
}
bool judge(){
vector<int> ve;
for(int i=0;i<n;++i)
if(ve.empty()||v[i]<v[ve[0]])
ve.clear(),ve.push_back(i);
else if(!ve.empty()&&v[i]==v[ve[0]])
ve.push_back(i);
ans+=v[ve[0]];
for(int i=0,k=v[ve[0]];i<n;++i)
v[i]-=k;
int slnum=0;
for(int i=0;i<n;++i)
if(v[i]+1>a[i])
++slnum;
if(!slnum)
return false;
if(se.find(v)!=se.end()){
ans=-2;
return false;
}
se.insert(v);
bool k=n-slnum>=slnum;
for(int i=0;i<n;++i)
if(!v[i])
v[i]=(k?a[i]:a[i]+b[i]);
return true;
}